2421 {
2422 DBG((
"%p %p", mgr,
c));
2424 c->next = mgr->active_connections;
2425 mgr->active_connections =
c;
2427 if (
c->next != NULL)
c->next->prev =
c;
2429 c->iface->vtable->add_conn(
c);
2430 }
2431}
2432
2439}
2440
2443 void *ev_data) {
2444 if (ev_handler == NULL) {
2445
2446
2447
2448
2450 }
2452 DBG((
"%p %s ev=%d ev_data=%p flags=0x%lx rmbl=%d smbl=%d", nc,
2453 ev_handler == nc->
handler ?
"user" :
"proto", ev, ev_data, nc->flags,
2454 (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
2455 }
2456
2457#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
2461 }
2462#endif
2463 if (ev_handler != NULL) {
2464 unsigned long flags_before = nc->
flags;
2465 ev_handler(nc, ev, ev_data
MG_UD_ARG(user_data));
2466
2467 if (ev_handler == nc->
handler && nc->
flags != flags_before) {
2468 nc->
flags = (flags_before & ~_MG_CALLBACK_MODIFIABLE_FLAGS_MASK) |
2470 }
2471 }
2474 DBG((
"%p after %s flags=0x%lx rmbl=%d smbl=%d", nc,
2475 ev_handler == nc->
handler ?
"user" :
"proto", nc->flags,
2476 (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
2477 }
2478#if !MG_ENABLE_CALLBACK_USERDATA
2479 (void) user_data;
2480#endif
2481}
2482
2484 if (
c->ev_timer_time > 0 && now >=
c->ev_timer_time) {
2485 double old_value =
c->ev_timer_time;
2486 c->ev_timer_time = 0;
2488 }
2489}
2490
2492 size_t avail;
2495 return avail > max ? max : avail;
2496}
2497
2499
2503 return 0;
2508 return 0;
2509 }
2512 return 0;
2513 }
2514#if MG_ENABLE_SSL
2516
2517
2518 int recved = 0;
2519 do {
2523 } while (recved > 0);
2524 }
2525#endif
2527 {
2528 time_t now_t = (time_t) now;
2530 }
2531 return 1;
2532}
2533
2537 }
2541 }
2542#if MG_ENABLE_SSL
2543 mg_ssl_if_conn_free(conn);
2544#endif
2547
2548 memset(conn, 0, sizeof(*conn));
2550}
2551
2553
2554
2556
2558 return;
2559 }
2560#if MG_ENABLE_SSL
2562 mg_ssl_if_conn_close_notify(conn);
2563 }
2564#endif
2565
2566
2567
2568
2574}
2575
2578 memset(&opts, 0, sizeof(opts));
2580}
2581
2584 memset(m, 0, sizeof(*m));
2585#if MG_ENABLE_BROADCAST
2587#endif
2589
2590#ifdef _WIN32
2591 {
2593 WSAStartup(MAKEWORD(2, 2), &
data);
2594 }
2595#elif defined(__unix__)
2596
2597
2598 signal(SIGPIPE, SIG_IGN);
2599#endif
2600
2601 {
2606 }
2609 }
2616 }
2617 }
2620 }
2621 DBG((
"=================================="));
2622 DBG((
"init mgr=%p", m));
2623#if MG_ENABLE_SSL
2624 {
2625 static int init_done;
2626 if (!init_done) {
2627 mg_ssl_if_init();
2628 init_done++;
2629 }
2630 }
2631#endif
2632}
2633
2636
2638 if (m == NULL) return;
2639
2641
2642#if MG_ENABLE_BROADCAST
2646#endif
2647
2649 tmp_conn = conn->
next;
2652 }
2653
2654 {
2659 }
2661 }
2662
2664}
2665
2668
2671 }
2672
2673 return (m->
num_calls - num_calls_before);
2674}
2675
2678 int len;
2679
2682 }
2683 if (
buf != mem &&
buf != NULL) {
2685 }
2686
2687 return len;
2688}
2689
2691 int len;
2692 va_list ap;
2693 va_start(ap, fmt);
2695 va_end(ap);
2696 return len;
2697}
2698
2699#if MG_ENABLE_SYNC_RESOLVER
2700
2701static int mg_resolve2(
const char *host,
struct in_addr *ina) {
2702#if MG_ENABLE_GETADDRINFO
2703 int rv = 0;
2704 struct addrinfo hints, *servinfo, *p;
2705 struct sockaddr_in *h = NULL;
2706 memset(&hints, 0, sizeof hints);
2707 hints.ai_family = AF_INET;
2708 hints.ai_socktype = SOCK_STREAM;
2709 if ((rv = getaddrinfo(host, NULL, NULL, &servinfo)) != 0) {
2711 return 0;
2712 }
2713 for (p = servinfo; p != NULL; p = p->ai_next) {
2714 memcpy(&h, &p->ai_addr, sizeof(h));
2715 memcpy(ina, &h->sin_addr, sizeof(*ina));
2716 }
2717 freeaddrinfo(servinfo);
2718 return 1;
2719#else
2720 struct hostent *he;
2721 if ((he = gethostbyname(host)) == NULL) {
2722 DBG((
"gethostbyname(%s) failed: %s", host, strerror(
mg_get_errno())));
2723 } else {
2724 memcpy(ina, he->h_addr_list[0], sizeof(*ina));
2725 return 1;
2726 }
2727 return 0;
2728#endif
2729}
2730
2731int mg_resolve(
const char *host,
char *buf,
size_t n) {
2732 struct in_addr ad;
2734}
2735#endif
2736
2741
2751
2752
2753
2754
2755
2757 } else {
2759 }
2760
2761 return conn;
2762}
2763
2768
2771 conn = NULL;
2772 }
2773 if (conn == NULL) {
2775 }
2776
2777 return conn;
2778}
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2794 int *proto, char *host, size_t host_len) {
2795 unsigned int a, b,
c,
d, port = 0;
2796 int ch, len = 0;
2797#if MG_ENABLE_IPV6
2799#endif
2800
2801
2802
2803
2804
2805
2806 memset(
sa, 0,
sizeof(*
sa));
2807 sa->
sin.sin_family = AF_INET;
2808
2809 *proto = SOCK_STREAM;
2810
2811 if (strncmp(
str,
"udp://", 6) == 0) {
2813 *proto = SOCK_DGRAM;
2814 }
else if (strncmp(
str,
"tcp://", 6) == 0) {
2816 }
2817
2818 if (sscanf(
str,
"%u.%u.%u.%u:%u%n", &a, &b, &
c, &
d, &port, &len) == 5) {
2819
2820 sa->
sin.sin_addr.s_addr =
2821 htonl(((uint32_t) a << 24) | ((uint32_t) b << 16) |
c << 8 |
d);
2822 sa->
sin.sin_port = htons((uint16_t) port);
2823#if MG_ENABLE_IPV6
2824 }
else if (sscanf(
str,
"[%99[^]]]:%u%n",
buf, &port, &len) == 2 &&
2826
2827 sa->
sin6.sin6_family = AF_INET6;
2828 sa->
sin.sin_port = htons((uint16_t) port);
2829#endif
2830#if MG_ENABLE_ASYNC_RESOLVER
2831 }
else if (strlen(
str) < host_len &&
2832 sscanf(
str,
"%[^ :]:%u%n", host, &port, &len) == 2) {
2833 sa->
sin.sin_port = htons((uint16_t) port);
2835
2836
2837
2838
2839
2840
2842 return 0;
2843 }
2844
2845#if MG_ENABLE_SYNC_RESOLVER
2847 return -1;
2848 }
2849#else
2850 return -1;
2851#endif
2852 }
2853#endif
2854 }
else if (sscanf(
str,
":%u%n", &port, &len) == 1 ||
2855 sscanf(
str,
"%u%n", &port, &len) == 1) {
2856
2857 sa->
sin.sin_port = htons((uint16_t) port);
2858 } else {
2859 return -1;
2860 }
2861
2862
2863 (void) host;
2864 (void) host_len;
2865
2867 return port < 0xffffUL && (ch == '\0' || ch == ',' || isspace(ch)) ? len : -1;
2868}
2869
2870#if MG_ENABLE_SSL
2873 int server_side = (nc->
listener != NULL);
2874 enum mg_ssl_if_result res;
2876 res = mg_ssl_if_handshake(nc);
2877
2878 if (res == MG_SSL_OK) {
2881 if (server_side) {
2883 } else {
2885 }
2886 } else if (res == MG_SSL_WANT_READ) {
2888 } else if (res == MG_SSL_WANT_WRITE) {
2890 } else {
2891 if (!server_side) {
2894 }
2896 }
2897}
2898#endif
2899
2903 memset(&opts, 0, sizeof(opts));
2905 if (nc == NULL) return NULL;
2914 return nc;
2915}
2916
2918 size_t sa_len) {
2922#if MG_ENABLE_SSL
2925 if (mg_ssl_if_conn_accept(nc, nc->
listener) == MG_SSL_OK) {
2926 mg_ssl_handshake(nc);
2927 } else {
2929 }
2930 } else
2931#endif
2932 {
2934 }
2935 (void) sa_len;
2936}
2937
2941}
2942
2945
2947 int res = 0;
2952 return -1;
2953 }
2954 do {
2956 if (len == 0) {
2957 res = -2;
2958 break;
2959 }
2962 }
2967 } else {
2969 }
2971 return res;
2972}
2973
2976}
2977
2980#if MG_ENABLE_SSL
2983 n = mg_ssl_if_read(nc,
buf, len);
2984 DBG((
"%p <- %d bytes (SSL)", nc,
n));
2986 if (
n == MG_SSL_WANT_READ) {
2989 } else {
2991 }
2993 nc->
flags &= ~MG_F_WANT_READ;
2994 }
2995 } else {
2996 mg_ssl_handshake(nc);
2997 }
2998 } else
2999#endif
3000 {
3002 DBG((
"%p <- %d bytes", nc,
n));
3003 }
3007#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
3010 }
3011#endif
3016 }
3019}
3020
3025 size_t sa_len =
sizeof(
sa);
3029 goto out;
3030 }
3032
3033
3034
3035
3036 lc = nc;
3038 if (memcmp(&nc->
sa.
sa, &
sa.sa, sa_len) == 0 && nc->
listener == lc) {
3039 break;
3040 }
3041 }
3042 if (nc == NULL) {
3044 memset(&opts, 0, sizeof(opts));
3045
3047 if (nc != NULL) {
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3069 }
3070 }
3071 }
3072 if (nc != NULL) {
3074 ntohs(nc->
sa.
sin.sin_port)));
3075 if (nc == lc) {
3077 } else {
3079 }
3082#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
3085 }
3086#endif
3089 }
3090 }
3091
3092out:
3095}
3096
3101
3103 return;
3104 }
3108 }
3109#if MG_ENABLE_SSL
3112 if (len > 0) {
3113 n = mg_ssl_if_write(nc, buf, len);
3114 DBG((
"%p -> %d bytes (SSL)", nc,
n));
3115 }
3117 if (
n == MG_SSL_WANT_WRITE) {
3120 } else {
3122 }
3123 } else {
3124 nc->
flags &= ~MG_F_WANT_WRITE;
3125 }
3126 } else {
3127 mg_ssl_handshake(nc);
3128 }
3129 } else
3130#endif
3131 if (len > 0) {
3134 } else {
3136 }
3137 DBG((
"%p -> %d bytes", nc,
n));
3138 }
3139
3140#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
3143 }
3144#endif
3151 }
3153}
3154
3155
3156
3157
3158
3159
3160
3162 int proto,
3164 LOG(
LL_DEBUG, (
"%p %s://%s:%hu", nc, proto == SOCK_DGRAM ?
"udp" :
"tcp",
3166
3168 if (proto == SOCK_DGRAM) {
3170 } else {
3172 }
3174 return nc;
3175}
3176
3179 (
"%p %s://%s:%hu -> %d", nc, (nc->
flags &
MG_F_UDP ?
"udp" :
"tcp"),
3181 nc->
flags &= ~MG_F_CONNECTING;
3184 }
3185#if MG_ENABLE_SSL
3187 mg_ssl_handshake(nc);
3188 } else
3189#endif
3190 {
3192 }
3193}
3194
3195#if MG_ENABLE_ASYNC_RESOLVER
3196
3197
3198
3199
3200
3201
3206 int failure = -1;
3207
3208 nc->
flags &= ~MG_F_RESOLVING;
3209 if (msg != NULL) {
3210
3211
3212
3215
3216
3217
3218
3220 4);
3223 return;
3224 }
3225 }
3226 }
3227
3231 }
3232
3233
3234
3235
3239}
3240#endif
3241
3246 memset(&opts, 0, sizeof(opts));
3248}
3249
3253 (void) ev;
3254 (void) ev_data;
3255#if MG_ENABLE_CALLBACK_USERDATA
3257#endif
3258}
3259
3265 int proto, rc;
3268
3270
3272
3274 return NULL;
3275 }
3276
3278 0) {
3279
3282 return NULL;
3283 }
3284
3287#if MG_ENABLE_CALLBACK_USERDATA
3289#else
3291#endif
3292
3293#if MG_ENABLE_SSL
3295 ("%p %s %s,%s,%s", nc, address, (opts.ssl_cert ? opts.ssl_cert : "-"),
3296 (opts.ssl_key ? opts.ssl_key : "-"),
3297 (opts.ssl_ca_cert ? opts.ssl_ca_cert : "-")));
3298
3299 if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL ||
3300 opts.ssl_psk_identity != NULL) {
3301 const char *err_msg = NULL;
3302 struct mg_ssl_if_conn_params params;
3306 return NULL;
3307 }
3308 memset(¶ms, 0, sizeof(params));
3309 params.cert = opts.ssl_cert;
3310 params.key = opts.ssl_key;
3311 params.ca_cert = opts.ssl_ca_cert;
3312 params.cipher_suites = opts.ssl_cipher_suites;
3313 params.psk_identity = opts.ssl_psk_identity;
3314 params.psk_key = opts.ssl_psk_key;
3315 if (opts.ssl_ca_cert != NULL) {
3316 if (opts.ssl_server_name != NULL) {
3317 if (strcmp(opts.ssl_server_name, "*") != 0) {
3318 params.server_name = opts.ssl_server_name;
3319 }
3320 } else if (rc == 0) {
3321 params.server_name = host;
3322 }
3323 }
3324 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
3327 return NULL;
3328 }
3330 }
3331#endif
3332
3333 if (rc == 0) {
3334#if MG_ENABLE_ASYNC_RESOLVER
3335
3336
3337
3338
3341 memset(&o, 0, sizeof(o));
3345 o) != 0) {
3348 return NULL;
3349 }
3352 return nc;
3353#else
3356 return NULL;
3357#endif
3358 } else {
3359
3361 }
3362}
3363
3368 memset(&opts, 0, sizeof(opts));
3370}
3371
3378 int proto, rc;
3381
3382#if MG_ENABLE_CALLBACK_USERDATA
3384#endif
3385
3387
3389
3392 return NULL;
3393 }
3394
3396 if (nc == NULL) {
3397 return NULL;
3398 }
3399
3403
3404#if MG_ENABLE_SSL
3405 DBG((
"%p %s %s,%s,%s", nc, address, (opts.ssl_cert ? opts.ssl_cert :
"-"),
3406 (opts.ssl_key ? opts.ssl_key : "-"),
3407 (opts.ssl_ca_cert ? opts.ssl_ca_cert : "-")));
3408
3409 if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) {
3410 const char *err_msg = NULL;
3411 struct mg_ssl_if_conn_params params;
3415 return NULL;
3416 }
3417 memset(¶ms, 0, sizeof(params));
3418 params.cert = opts.ssl_cert;
3419 params.key = opts.ssl_key;
3420 params.ca_cert = opts.ssl_ca_cert;
3421 params.cipher_suites = opts.ssl_cipher_suites;
3422 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
3425 return NULL;
3426 }
3428 }
3429#endif
3430
3433 } else {
3435 }
3436 if (rc != 0) {
3437 DBG((
"Failed to open listener: %d", rc));
3440 return NULL;
3441 }
3443
3444 return nc;
3445}
3446
3449}
3450
3451#if MG_ENABLE_BROADCAST
3453 size_t len) {
3455
3456
3457
3458
3459
3460
3461
3462
3465 size_t dummy;
3466
3472 (void) dummy;
3473 }
3474}
3475#endif
3476
3478 return n >= 0 &&
n <= 255;
3479}
3480
3481static int parse_net(
const char *spec, uint32_t *net, uint32_t *
mask) {
3482 int n, a, b,
c,
d, slash = 32, len = 0;
3483
3484 if ((sscanf(spec,
"%d.%d.%d.%d/%d%n", &a, &b, &
c, &
d, &slash, &
n) == 5 ||
3485 sscanf(spec,
"%d.%d.%d.%d%n", &a, &b, &
c, &
d, &
n) == 4) &&
3487 slash < 33) {
3489 *net =
3490 ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t)
c << 8) |
d;
3491 *
mask = slash ? 0xffffffffU << (32 - slash) : 0;
3492 }
3493
3494 return len;
3495}
3496
3498 int allowed, flag;
3501
3502
3503 allowed = (acl == NULL || *acl == '\0') ? '+' : '-';
3504
3507 if ((flag != '+' && flag != '-') ||
3509 return -1;
3510 }
3511
3512 if (net == (remote_ip &
mask)) {
3513 allowed = flag;
3514 }
3515 }
3516
3517 DBG((
"%08x %c", (
unsigned int) remote_ip, allowed));
3518 return allowed == '+';
3519}
3520
3521
3525}
3526
3528 double result =
c->ev_timer_time;
3529 c->ev_timer_time = timestamp;
3530
3531
3532
3533
3534
3536 (unsigned long) timestamp));
3539 }
3540 return result;
3541}
3542
3546 }
3547}
3548
3552}
3553
3558#if MG_ENABLE_CALLBACK_USERDATA
3560#endif
3561
3563 if (nc != NULL) {
3566 }
3567 return nc;
3568}
3569
3574 memset(&opts, 0, sizeof(opts));
3576}
3577
3580}
3581#ifdef MG_MODULE_LINES
3582#line 1 "mongoose/src/mg_net_if_socket.h"
3583#endif
3584
3585
3586
3587
3588
3589#ifndef CS_MONGOOSE_SRC_NET_IF_SOCKET_H_
3590#define CS_MONGOOSE_SRC_NET_IF_SOCKET_H_
3591
3592
3593
3594#ifdef __cplusplus
3595extern "C" {
3596#endif
3597
3598#ifndef MG_ENABLE_NET_IF_SOCKET
3599#define MG_ENABLE_NET_IF_SOCKET MG_NET_IF == MG_NET_IF_SOCKET
3600#endif
3601
3603
3604#ifdef __cplusplus
3605}
3606#endif
3607
3608#endif
3609#ifdef MG_MODULE_LINES
3610#line 1 "mongoose/src/mg_net_if_socks.h"
3611#endif
3612
3613
3614
3615
3616
3617#ifndef CS_MONGOOSE_SRC_NET_IF_SOCKS_H_
3618#define CS_MONGOOSE_SRC_NET_IF_SOCKS_H_
3619
3620#if MG_ENABLE_SOCKS
3621
3622
3623#ifdef __cplusplus
3624extern "C" {
3625#endif
3626
3628
3629#ifdef __cplusplus
3630}
3631#endif
3632#endif
3633#endif
3634#ifdef MG_MODULE_LINES
3635#line 1 "mongoose/src/mg_net_if.c"
3636#endif
3637
3638
3639
3640
3642
3645};
3646
3648
3655 return iface;
3656}
3657
3662 if (from != NULL) {
3666 break;
3667 }
3668 }
3669 }
3670
3674 }
3675 }
3676 return NULL;
3677}
3678
3680 double min_timer = 0;
3686 }
3687 }
3688 return min_timer;
3689}
3690#ifdef MG_MODULE_LINES
3691#line 1 "mongoose/src/mg_net_if_null.c"
3692#endif
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3715}
3716
3719}
3720
3725 return -1;
3726}
3727
3732 return -1;
3733}
3734
3736 size_t len) {
3739 (void) len;
3740 return -1;
3741}
3742
3744 size_t len) {
3747 (void) len;
3748 return -1;
3749}
3750
3754 (void) len;
3755 return -1;
3756}
3757
3762 (void) len;
3764 (void) sa_len;
3765 return -1;
3766}
3767
3770 return 1;
3771}
3772
3775}
3776
3780}
3781
3784}
3785
3788}
3789
3793}
3794
3797}
3798
3803
3807 }
3808 (void) timeout_ms;
3809 return (time_t) now;
3810}
3811
3815 (void) remote;
3817}
3818
3819#define MG_NULL_IFACE_VTABLE \
3820 { \
3821 mg_null_if_init, mg_null_if_free, mg_null_if_add_conn, \
3822 mg_null_if_remove_conn, mg_null_if_poll, mg_null_if_listen_tcp, \
3823 mg_null_if_listen_udp, mg_null_if_connect_tcp, mg_null_if_connect_udp, \
3824 mg_null_if_tcp_send, mg_null_if_udp_send, mg_null_if_tcp_recv, \
3825 mg_null_if_udp_recv, mg_null_if_create_conn, mg_null_if_destroy_conn, \
3826 mg_null_if_sock_set, mg_null_if_get_conn_addr, \
3827 }
3828
3829
3830
3831#if MG_NET_IF == MG_NET_IF_NULL
3833#endif
3834#ifdef MG_MODULE_LINES
3835#line 1 "mongoose/src/mg_net_if_socket.c"
3836#endif
3837
3838
3839
3840
3841
3842#if MG_ENABLE_NET_IF_SOCKET
3843
3844
3845
3846
3847
3849 int proto);
3850
3852#ifdef _WIN32
3853 unsigned long on = 1;
3854 ioctlsocket(sock, FIONBIO, &on);
3855#else
3856 int flags = fcntl(sock, F_GETFL, 0);
3857 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
3858#endif
3859}
3860
3863 return err != EINPROGRESS && err != EWOULDBLOCK
3864#ifndef WINCE
3865 && err != EAGAIN && err != EINTR
3866#endif
3867#ifdef _WIN32
3868 && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK
3869#endif
3870 ;
3871}
3872
3875 int rc, proto = 0;
3876 nc->
sock =
socket(AF_INET, SOCK_STREAM, proto);
3879 return;
3880 }
3881#if !defined(MG_ESP8266)
3883#endif
3884 rc = connect(nc->
sock, &sa->
sa,
sizeof(sa->
sin));
3888}
3889
3894 return;
3895 }
3897 int optval = 1;
3898 if (setsockopt(nc->
sock, SOL_SOCKET, SO_BROADCAST, (
const char *) &optval,
3899 sizeof(optval)) < 0) {
3901 return;
3902 }
3903 }
3905}
3906
3909 int proto = 0;
3913 }
3915 return 0;
3916}
3917
3923 return 0;
3924}
3925
3927 size_t len) {
3931}
3932
3934 size_t len) {
3935 int n = sendto(nc->
sock, buf, len, 0, &nc->
sa.
sa,
sizeof(nc->
sa.
sin));
3938}
3939
3941 size_t len) {
3944
3948 }
3950}
3951
3954 size_t *sa_len) {
3955 socklen_t sa_len_st = *sa_len;
3956 int n = recvfrom(nc->
sock, buf, len, 0, &sa->
sa, &sa_len_st);
3957 *sa_len = sa_len_st;
3960}
3961
3963 (void) nc;
3964 return 1;
3965}
3966
3971 } else {
3972
3974 }
3976}
3977
3981 socklen_t sa_len =
sizeof(
sa);
3982
3983 sock_t sock = accept(lc->
sock, &
sa.sa, &sa_len);
3987 }
3988 return 0;
3989 }
3991 if (nc == NULL) {
3993 return 0;
3994 }
3996 ntohs(
sa.sin.sin_port)));
3999 return 1;
4000}
4001
4002
4004 int proto) {
4005 socklen_t sa_len =
4006 (
sa->sa.sa_family == AF_INET) ?
sizeof(
sa->sin) :
sizeof(
sa->sin6);
4008#if !MG_LWIP
4009 int on = 1;
4010#endif
4011
4014#if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE) && !defined(WINCE)
4015
4016 !setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &on,
4017 sizeof(on)) &&
4018#endif
4019
4020#if !defined(_WIN32) || !defined(SO_EXCLUSIVEADDRUSE)
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030 !setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)) &&
4031#endif
4032#endif
4033
4034 !bind(sock, &
sa->sa, sa_len) &&
4036#if !MG_LWIP
4038
4039 (void) getsockname(sock, &
sa->sa, &sa_len);
4040#endif
4044 }
4045
4046 return sock;
4047}
4048
4049#define _MG_F_FD_CAN_READ 1
4050#define _MG_F_FD_CAN_WRITE 1 << 1
4051#define _MG_F_FD_ERROR 1 << 2
4052
4054 int worth_logging =
4056 if (worth_logging) {
4057 DBG((
"%p fd=%d fd_flags=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock,
4060 }
4061
4063
4065 if (fd_flags != 0) {
4066 int err = 0;
4067#if !defined(MG_ESP8266)
4069 socklen_t len = sizeof(err);
4070 int ret =
4071 getsockopt(nc->
sock, SOL_SOCKET, SO_ERROR, (
char *) &err, &len);
4072 if (ret != 0) {
4073 err = 1;
4074 } else if (err == EAGAIN || err == EWOULDBLOCK) {
4075 err = 0;
4076 }
4077 }
4078#else
4079
4080
4081
4083#endif
4085 }
else if (nc->
err != 0) {
4087 }
4088 }
4089
4093 } else {
4095
4096
4097
4098
4099
4101 } else {
4103 }
4104 }
4105 }
4106
4108
4109 if (worth_logging) {
4110 DBG((
"%p after fd=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock,
4112 }
4113}
4114
4115#if MG_ENABLE_BROADCAST
4118 int len =
4120 DBG((
"read %d from ctl socket", len));
4126 }
4127 }
4128
4129
4131 (void) dummy;
4132}
4133#endif
4134
4135
4141}
4142
4146#if MG_ENABLE_BROADCAST
4148#endif
4149}
4150
4153}
4154
4156 (void) nc;
4157}
4158
4160 (void) nc;
4161}
4162
4165#ifdef __unix__
4167#endif
4168 ) {
4172 }
4173 }
4174}
4175
4179 double min_timer;
4182 fd_set read_set, write_set, err_set;
4184 int num_fds, num_ev, num_timers = 0;
4185#ifdef __unix__
4186 int try_dup = 1;
4187#endif
4188
4189 FD_ZERO(&read_set);
4190 FD_ZERO(&write_set);
4191 FD_ZERO(&err_set);
4192#if MG_ENABLE_BROADCAST
4194#endif
4195
4196
4197
4198
4199
4200 min_timer = 0;
4203
4205 num_fds++;
4206
4207#ifdef __unix__
4208
4210 int new_sock = dup(nc->
sock);
4211 if (new_sock >= 0) {
4214 DBG((
"new sock %d -> %d", nc->
sock, new_sock));
4215 nc->
sock = new_sock;
4216 } else {
4218 DBG((
"new sock is still larger than FD_SETSIZE, disregard"));
4219 try_dup = 0;
4220 }
4221 } else {
4222 try_dup = 0;
4223 }
4224 }
4225#endif
4226
4230 }
4231
4236 }
4237 }
4238
4242 }
4243 num_timers++;
4244 }
4245 }
4246
4247
4248
4249
4250
4251 if (num_timers > 0) {
4252 double timer_timeout_ms = (min_timer -
mg_time()) * 1000 + 1 ;
4253 if (timer_timeout_ms < timeout_ms) {
4254 timeout_ms = (int) timer_timeout_ms;
4255 }
4256 }
4257 if (timeout_ms < 0) timeout_ms = 0;
4258
4259 tv.tv_sec = timeout_ms / 1000;
4260 tv.tv_usec = (timeout_ms % 1000) * 1000;
4261
4262 num_ev = select((
int) max_fd + 1, &read_set, &write_set, &err_set, &
tv);
4264#if 0
4265 DBG((
"select @ %ld num_ev=%d of %d, timeout=%d", (
long) now, num_ev, num_fds,
4266 timeout_ms));
4267#endif
4268
4269#if MG_ENABLE_BROADCAST
4271 FD_ISSET(mgr->
ctl[1], &read_set)) {
4273 }
4274#endif
4275
4277 int fd_flags = 0;
4279 if (num_ev > 0) {
4280 fd_flags = (FD_ISSET(nc->
sock, &read_set) &&
4283 : 0) |
4286 }
4287#if MG_LWIP
4288
4291 }
4292#endif
4293 }
4296 }
4297
4298 return (time_t) now;
4299}
4300
4301#if MG_ENABLE_BROADCAST
4302MG_INTERNAL void mg_socketpair_close(sock_t *sock) {
4303 while (1) {
4304 if (
closesocket(*sock) == -1 && errno == EINTR)
continue;
4305 break;
4306 }
4308}
4309
4311mg_socketpair_accept(sock_t sock,
union socket_address *sa, socklen_t sa_len) {
4312 sock_t rc;
4313 while (1) {
4315 errno == EINTR)
4316 continue;
4317 break;
4318 }
4319 return rc;
4320}
4321
4324 sock_t sock;
4325 socklen_t len =
sizeof(
sa.sin);
4326 int ret = 0;
4327
4329
4330 (void) memset(&
sa, 0,
sizeof(
sa));
4331 sa.
sin.sin_family = AF_INET;
4332 sa.sin.sin_addr.s_addr = htonl(0x7f000001);
4334
4336 }
else if (bind(sock, &
sa.sa, len) != 0) {
4337 } else if (sock_type == SOCK_STREAM && listen(sock, 1) != 0) {
4338 }
else if (getsockname(sock, &
sa.sa, &len) != 0) {
4340 }
else if (sock_type == SOCK_STREAM && connect(sp[0], &
sa.sa, len) != 0) {
4341 } else if (sock_type == SOCK_DGRAM &&
4342 (bind(sp[0], &sa2.sa, len) != 0 ||
4343 getsockname(sp[0], &sa2.sa, &len) != 0 ||
4344 connect(sp[0], &
sa.sa, len) != 0 ||
4345 connect(sock, &sa2.sa, len) != 0)) {
4346 } else if ((sp[1] = (sock_type == SOCK_DGRAM ? sock : mg_socketpair_accept(
4347 sock, &
sa, len))) ==
4349 } else {
4352 if (sock_type == SOCK_STREAM) mg_socketpair_close(&sock);
4353 ret = 1;
4354 }
4355
4356 if (!ret) {
4360 }
4361
4362 return ret;
4363}
4364#endif
4365
4368 socklen_t slen = sizeof(*sa);
4369 memset(
sa, 0, slen);
4370 if (remote) {
4371 getpeername(sock, &
sa->sa, &slen);
4372 } else {
4373 getsockname(sock, &
sa->sa, &slen);
4374 }
4375}
4376
4377void mg_sock_to_str(sock_t sock,
char *buf,
size_t len,
int flags) {
4381}
4382
4386 memcpy(
sa, &nc->
sa,
sizeof(*
sa));
4387 return;
4388 }
4390}
4391
4392
4393#define MG_SOCKET_IFACE_VTABLE \
4394 { \
4395 mg_socket_if_init, \
4396 mg_socket_if_free, \
4397 mg_socket_if_add_conn, \
4398 mg_socket_if_remove_conn, \
4399 mg_socket_if_poll, \
4400 mg_socket_if_listen_tcp, \
4401 mg_socket_if_listen_udp, \
4402 mg_socket_if_connect_tcp, \
4403 mg_socket_if_connect_udp, \
4404 mg_socket_if_tcp_send, \
4405 mg_socket_if_udp_send, \
4406 mg_socket_if_tcp_recv, \
4407 mg_socket_if_udp_recv, \
4408 mg_socket_if_create_conn, \
4409 mg_socket_if_destroy_conn, \
4410 mg_socket_if_sock_set, \
4411 mg_socket_if_get_conn_addr, \
4412 }
4413
4414
4416#if MG_NET_IF == MG_NET_IF_SOCKET
4418#endif
4419
4420#endif
4421#ifdef MG_MODULE_LINES
4422#line 1 "mongoose/src/mg_net_if_socks.c"
4423#endif
4424
4425
4426
4427
4428
4429#if MG_ENABLE_SOCKS
4430
4431struct socksdata {
4432 char *proxy_addr;
4435};
4436
4437static void socks_if_disband(
struct socksdata *
d) {
4441 d->c->user_data = NULL;
4443 }
4446 d->s->user_data = NULL;
4448 }
4449}
4450
4452 struct socksdata *
d = (
struct socksdata *) s->
user_data;
4453 if (
d == NULL ||
d->c == NULL || !(s->flags & MG_SOCKS_CONNECT_DONE) ||
4455 return;
4456 }
4459}
4460
4461static void socks_if_handler(
struct mg_connection *
c,
int ev,
void *ev_data) {
4462 struct socksdata *
d = (
struct socksdata *)
c->user_data;
4463 if (
d == NULL)
return;
4465 int res = *(int *) ev_data;
4466 if (res == 0) {
4467
4468 unsigned char buf[] = {MG_SOCKS_VERSION, 1, MG_SOCKS_HANDSHAKE_NOAUTH};
4470 LOG(
LL_DEBUG, (
"Sent handshake to %s",
d->proxy_addr));
4471 } else {
4472 LOG(
LL_ERROR, (
"Cannot connect to %s: %d",
d->proxy_addr, res));
4474 }
4476 socks_if_disband(
d);
4478
4479 if (!(
c->flags & MG_SOCKS_HANDSHAKE_DONE)) {
4480
4481 unsigned char buf[10] = {MG_SOCKS_VERSION, MG_SOCKS_CMD_CONNECT, 0,
4482 MG_SOCKS_ADDR_IPV4};
4483 if (
c->recv_mbuf.len < 2)
return;
4484 if ((
unsigned char)
c->recv_mbuf.buf[1] == MG_SOCKS_HANDSHAKE_FAILURE) {
4486 socks_if_disband(
d);
4487 return;
4488 }
4490 c->flags |= MG_SOCKS_HANDSHAKE_DONE;
4491
4492
4493 memcpy(buf + 4, &
d->c->sa.sin.sin_addr, 4);
4494 memcpy(buf + 8, &
d->c->sa.sin.sin_port, 2);
4497 }
4498
4499 if ((
c->flags & MG_SOCKS_HANDSHAKE_DONE) &&
4500 !(
c->flags & MG_SOCKS_CONNECT_DONE)) {
4501 if (
c->recv_mbuf.len < 10)
return;
4502 if (
c->recv_mbuf.buf[1] != MG_SOCKS_SUCCESS) {
4503 LOG(
LL_ERROR, (
"Socks connection error: %d",
c->recv_mbuf.buf[1]));
4504 socks_if_disband(
d);
4505 return;
4506 }
4508 c->flags |= MG_SOCKS_CONNECT_DONE;
4511 }
4515 }
4516}
4517
4520 struct socksdata *
d = (
struct socksdata *)
c->iface->data;
4523 d->s->user_data =
d;
4525 (void) sa;
4526}
4527
4530}
4531
4535 (void) sa;
4536 return 0;
4537}
4538
4542 (void) sa;
4543 return -1;
4544}
4545
4546static int mg_socks_if_tcp_send(
struct mg_connection *
c,
const void *buf,
4547 size_t len) {
4548 int res;
4549 struct socksdata *
d = (
struct socksdata *)
c->iface->data;
4550 if (
d->s == NULL)
return -1;
4552 DBG((
"%p -> %d -> %p",
c, res,
d->s));
4553 return res;
4554}
4555
4556static int mg_socks_if_udp_send(
struct mg_connection *
c,
const void *buf,
4557 size_t len) {
4559 (void) buf;
4560 (void) len;
4561 return -1;
4562}
4563
4564int mg_socks_if_tcp_recv(
struct mg_connection *
c,
void *buf,
size_t len) {
4565 struct socksdata *
d = (
struct socksdata *)
c->iface->data;
4566 if (
d->s == NULL)
return -1;
4567 if (len >
d->s->recv_mbuf.len) len =
d->s->recv_mbuf.len;
4568 if (len > 0) {
4569 memcpy(buf,
d->s->recv_mbuf.buf, len);
4571 }
4572 DBG((
"%p <- %d <- %p",
c, (
int) len,
d->s));
4573 return len;
4574}
4575
4576int mg_socks_if_udp_recv(
struct mg_connection *
c,
void *buf,
size_t len,
4579 (void) buf;
4580 (void) len;
4581 (void) sa;
4582 (void) sa_len;
4583 return -1;
4584}
4585
4588 return 1;
4589}
4590
4592 c->iface->vtable->free(
c->iface);
4596}
4597
4598static void mg_socks_if_sock_set(
struct mg_connection *
c, sock_t sock) {
4600 (void) sock;
4601}
4602
4603static void mg_socks_if_init(
struct mg_iface *iface) {
4604 (void) iface;
4605}
4606
4607static void mg_socks_if_free(
struct mg_iface *iface) {
4608 struct socksdata *
d = (
struct socksdata *) iface->
data;
4611 socks_if_disband(
d);
4615 }
4616}
4617
4620}
4621
4624}
4625
4626static time_t mg_socks_if_poll(
struct mg_iface *iface,
int timeout_ms) {
4628 (void) iface;
4629 (void) timeout_ms;
4631}
4632
4633static void mg_socks_if_get_conn_addr(
struct mg_connection *
c,
int remote,
4637 (void) remote;
4638 (void) sa;
4639}
4640
4642 mg_socks_if_init, mg_socks_if_free,
4643 mg_socks_if_add_conn, mg_socks_if_remove_conn,
4644 mg_socks_if_poll, mg_socks_if_listen_tcp,
4645 mg_socks_if_listen_udp, mg_socks_if_connect_tcp,
4646 mg_socks_if_connect_udp, mg_socks_if_tcp_send,
4647 mg_socks_if_udp_send, mg_socks_if_tcp_recv,
4648 mg_socks_if_udp_recv, mg_socks_if_create_conn,
4649 mg_socks_if_destroy_conn, mg_socks_if_sock_set,
4650 mg_socks_if_get_conn_addr,
4651};
4652
4656 ((
struct socksdata *) iface->
data)->proxy_addr = strdup(proxy_addr);
4657 return iface;
4658}
4659
4660#endif
4661#ifdef MG_MODULE_LINES
4662#line 1 "mongoose/src/mg_ssl_if_openssl.c"
4663#endif
4664
4665
4666
4667
4668
4669#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_OPENSSL
4670
4671#ifdef __APPLE__
4672#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
4673#endif
4674
4675#include <openssl/ssl.h>
4676#ifndef KR_VERSION
4677#include <openssl/tls1.h>
4678#endif
4679
4680struct mg_ssl_if_ctx {
4684 size_t identity_len;
4685};
4686
4687void mg_ssl_if_init() {
4688 SSL_library_init();
4689}
4690
4691enum mg_ssl_if_result mg_ssl_if_conn_accept(
struct mg_connection *nc,
4693 struct mg_ssl_if_ctx *ctx =
4694 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
4695 struct mg_ssl_if_ctx *lc_ctx = (struct mg_ssl_if_ctx *) lc->ssl_if_data;
4696 nc->ssl_if_data = ctx;
4697 if (ctx == NULL || lc_ctx == NULL) return MG_SSL_ERROR;
4698 ctx->ssl_ctx = lc_ctx->ssl_ctx;
4699 if ((ctx->ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
4700 return MG_SSL_ERROR;
4701 }
4702 return MG_SSL_OK;
4703}
4704
4705static enum mg_ssl_if_result mg_use_cert(
SSL_CTX *ctx,
const char *cert,
4706 const char *
key,
const char **err_msg);
4707static enum mg_ssl_if_result mg_use_ca_cert(
SSL_CTX *ctx,
const char *cert);
4708static enum mg_ssl_if_result mg_set_cipher_list(
SSL_CTX *ctx,
const char *cl);
4709static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(struct mg_ssl_if_ctx *ctx,
4710 const char *identity,
4711 const char *key_str);
4712
4713enum mg_ssl_if_result mg_ssl_if_conn_init(
4714 struct mg_connection *nc,
const struct mg_ssl_if_conn_params *params,
4715 const char **err_msg) {
4716 struct mg_ssl_if_ctx *ctx =
4717 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
4718 DBG((
"%p %s,%s,%s", nc, (params->cert ? params->cert :
""),
4719 (params->
key ? params->
key :
""),
4720 (params->ca_cert ? params->ca_cert : "")));
4721 if (ctx == NULL) {
4723 return MG_SSL_ERROR;
4724 }
4725 nc->ssl_if_data = ctx;
4727 ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
4728 } else {
4729 ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
4730 }
4731 if (ctx->ssl_ctx == NULL) {
4733 return MG_SSL_ERROR;
4734 }
4735
4736#ifndef KR_VERSION
4737
4738 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2);
4739 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv3);
4740 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_TLSv1);
4741#ifdef MG_SSL_OPENSSL_NO_COMPRESSION
4742 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_COMPRESSION);
4743#endif
4744#ifdef MG_SSL_OPENSSL_CIPHER_SERVER_PREFERENCE
4745 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
4746#endif
4747#else
4748
4749#endif
4750
4751 if (params->cert != NULL &&
4752 mg_use_cert(ctx->ssl_ctx, params->cert, params->key, err_msg) !=
4753 MG_SSL_OK) {
4754 return MG_SSL_ERROR;
4755 }
4756
4757 if (params->ca_cert != NULL &&
4758 mg_use_ca_cert(ctx->ssl_ctx, params->ca_cert) != MG_SSL_OK) {
4760 return MG_SSL_ERROR;
4761 }
4762
4763 if (mg_set_cipher_list(ctx->ssl_ctx, params->cipher_suites) != MG_SSL_OK) {
4765 return MG_SSL_ERROR;
4766 }
4767
4769 if (mg_ssl_if_ossl_set_psk(ctx, params->psk_identity, params->psk_key) !=
4770 MG_SSL_OK) {
4772 return MG_SSL_ERROR;
4773 }
4774
4776 (ctx->ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
4778 return MG_SSL_ERROR;
4779 }
4780
4781 if (params->server_name != NULL) {
4782#ifdef KR_VERSION
4783 SSL_CTX_kr_set_verify_name(ctx->ssl_ctx, params->server_name);
4784#else
4785 SSL_set_tlsext_host_name(ctx->ssl, params->server_name);
4786#endif
4787 }
4788
4790
4791 return MG_SSL_OK;
4792}
4793
4794static enum mg_ssl_if_result mg_ssl_if_ssl_err(
struct mg_connection *nc,
4795 int res) {
4796 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
4797 int err = SSL_get_error(ctx->ssl, res);
4798 if (err == SSL_ERROR_WANT_READ) return MG_SSL_WANT_READ;
4799 if (err == SSL_ERROR_WANT_WRITE) return MG_SSL_WANT_WRITE;
4800 DBG((
"%p %p SSL error: %d %d", nc, ctx->ssl_ctx, res, err));
4802 return MG_SSL_ERROR;
4803}
4804
4805enum mg_ssl_if_result mg_ssl_if_handshake(
struct mg_connection *nc) {
4806 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
4807 int server_side = (nc->
listener != NULL);
4808 int res;
4809
4810 if (SSL_get_fd(ctx->ssl) < 0) {
4811 if (SSL_set_fd(ctx->ssl, nc->
sock) != 1)
return MG_SSL_ERROR;
4812 }
4813 res = server_side ? SSL_accept(ctx->ssl) : SSL_connect(ctx->ssl);
4814 if (res != 1) return mg_ssl_if_ssl_err(nc, res);
4815 return MG_SSL_OK;
4816}
4817
4818int mg_ssl_if_read(
struct mg_connection *nc,
void *buf,
size_t buf_size) {
4819 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
4820 int n = SSL_read(ctx->ssl, buf, buf_size);
4821 DBG((
"%p %d -> %d", nc, (
int) buf_size,
n));
4822 if (
n < 0)
return mg_ssl_if_ssl_err(nc,
n);
4825}
4826
4828 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
4829 int n = SSL_write(ctx->ssl,
data, len);
4830 DBG((
"%p %d -> %d", nc, (
int) len,
n));
4831 if (
n <= 0)
return mg_ssl_if_ssl_err(nc,
n);
4833}
4834
4836 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
4837 if (ctx == NULL) return;
4838 SSL_shutdown(ctx->ssl);
4839}
4840
4842 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
4843 if (ctx == NULL) return;
4844 nc->ssl_if_data = NULL;
4845 if (ctx->ssl != NULL) SSL_free(ctx->ssl);
4846 if (ctx->ssl_ctx != NULL && nc->
listener == NULL) SSL_CTX_free(ctx->ssl_ctx);
4848 memset(ctx, 0, sizeof(*ctx));
4850}
4851
4852
4853
4854
4855
4856static const char mg_s_cipher_list[] =
4857#if defined(MG_SSL_CRYPTO_MODERN)
4858 "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:"
4859 "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:"
4860 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
4861 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
4862 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
4863 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
4864 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
4865 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:"
4866 "!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"
4867#elif defined(MG_SSL_CRYPTO_OLD)
4868 "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:"
4869 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"
4870 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
4871 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
4872 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
4873 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
4874 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
4875 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:"
4876 "ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:"
4877 "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:"
4878 "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:"
4879 "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
4880#else
4881 "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:"
4882 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"
4883 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
4884 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
4885 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
4886 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
4887 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
4888 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:"
4889 "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:"
4890 "DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:"
4891 "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:"
4892 "!CAMELLIA:"
4893 "!RSA:"
4894 "!DES:"
4895 "!3DES"
4896
4897#endif
4898 ;
4899
4900
4901
4902
4903
4904#if !MG_DISABLE_PFS && !defined(KR_VERSION)
4905static const char mg_s_default_dh_params[] =
4906 "\
4907-----BEGIN DH PARAMETERS-----\n\
4908MIIBCAKCAQEAlvbgD/qh9znWIlGFcV0zdltD7rq8FeShIqIhkQ0C7hYFThrBvF2E\n\
4909Z9bmgaP+sfQwGpVlv9mtaWjvERbu6mEG7JTkgmVUJrUt/wiRzwTaCXBqZkdUO8Tq\n\
4910+E6VOEQAilstG90ikN1Tfo+K6+X68XkRUIlgawBTKuvKVwBhuvlqTGerOtnXWnrt\n\
4911ym//hd3cd5PBYGBix0i7oR4xdghvfR2WLVu0LgdThTBb6XP7gLd19cQ1JuBtAajZ\n\
4912wMuPn7qlUkEFDIkAZy59/Hue/H2Q2vU/JsvVhHWCQBL4F1ofEAt50il6ZxR1QfFK\n\
49139VGKDC4oOgm9DlxwwBoC2FjqmvQlqVV3kwIBAg==\n\
4914-----END DH PARAMETERS-----\n";
4915#endif
4916
4917static enum mg_ssl_if_result mg_use_ca_cert(
SSL_CTX *ctx,
const char *cert) {
4918 if (cert == NULL || strcmp(cert, "*") == 0) {
4919 return MG_SSL_OK;
4920 }
4921 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
4922 return SSL_CTX_load_verify_locations(ctx, cert, NULL) == 1 ? MG_SSL_OK
4923 : MG_SSL_ERROR;
4924}
4925
4926static enum mg_ssl_if_result mg_use_cert(
SSL_CTX *ctx,
const char *cert,
4928 const char **err_msg) {
4929 if (
key == NULL)
key = cert;
4930 if (cert == NULL || cert[0] ==
'\0' ||
key == NULL ||
key[0] ==
'\0') {
4931 return MG_SSL_OK;
4932 } else if (SSL_CTX_use_certificate_file(ctx, cert, 1) == 0) {
4934 return MG_SSL_ERROR;
4935 }
else if (SSL_CTX_use_PrivateKey_file(ctx,
key, 1) == 0) {
4937 return MG_SSL_ERROR;
4938 } else if (SSL_CTX_use_certificate_chain_file(ctx, cert) == 0) {
4940 return MG_SSL_ERROR;
4941 } else {
4942 SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
4943#if !MG_DISABLE_PFS && !defined(KR_VERSION)
4944 BIO *bio = NULL;
4945 DH *dh = NULL;
4946
4947
4948 bio = BIO_new_file(cert, "r");
4949 if (bio != NULL) {
4950 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
4951 BIO_free(bio);
4952 }
4953
4954
4955
4956
4957 if (dh == NULL) {
4958 bio = BIO_new_mem_buf((void *) mg_s_default_dh_params, -1);
4959 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
4960 BIO_free(bio);
4961 }
4962 if (dh != NULL) {
4963 SSL_CTX_set_tmp_dh(ctx, dh);
4964 SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
4965 DH_free(dh);
4966 }
4967#if OPENSSL_VERSION_NUMBER > 0x10002000L
4968 SSL_CTX_set_ecdh_auto(ctx, 1);
4969#endif
4970#endif
4971 }
4972 return MG_SSL_OK;
4973}
4974
4975static enum mg_ssl_if_result mg_set_cipher_list(
SSL_CTX *ctx,
const char *cl) {
4976 return (SSL_CTX_set_cipher_list(ctx, cl ? cl : mg_s_cipher_list) == 1
4977 ? MG_SSL_OK
4978 : MG_SSL_ERROR);
4979}
4980
4981#if !defined(KR_VERSION) && !defined(LIBRESSL_VERSION_NUMBER)
4982static unsigned int mg_ssl_if_ossl_psk_cb(
SSL *ssl,
const char *hint,
4983 char *identity,
4984 unsigned int max_identity_len,
4985 unsigned char *psk,
4986 unsigned int max_psk_len) {
4987 struct mg_ssl_if_ctx *ctx =
4988 (struct mg_ssl_if_ctx *) SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl));
4989 size_t key_len = ctx->psk.len - ctx->identity_len - 1;
4990 DBG((
"hint: '%s'", (hint ? hint :
"")));
4991 if (ctx->identity_len + 1 > max_identity_len) {
4992 DBG((
"identity too long"));
4993 return 0;
4994 }
4995 if (key_len > max_psk_len) {
4996 DBG((
"key too long"));
4997 return 0;
4998 }
4999 memcpy(identity, ctx->psk.buf, ctx->identity_len + 1);
5000 memcpy(psk, ctx->psk.buf + ctx->identity_len + 1, key_len);
5001 (void) ssl;
5002 return key_len;
5003}
5004
5005static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(struct mg_ssl_if_ctx *ctx,
5006 const char *identity,
5007 const char *key_str) {
5008 unsigned char key[32];
5009 size_t key_len;
5011 if (identity == NULL && key_str == NULL) return MG_SSL_OK;
5012 if (identity == NULL || key_str == NULL) return MG_SSL_ERROR;
5013 key_len = strlen(key_str);
5014 if (key_len != 32 && key_len != 64) return MG_SSL_ERROR;
5015 memset(
key, 0,
sizeof(
key));
5016 key_len = 0;
5017 for (
i = 0; key_str[
i] !=
'\0';
i++) {
5019 char hc = tolower((
int) key_str[
i]);
5020 if (hc >= '0' && hc <= '9') {
5022 } else if (hc >= 'a' && hc <= 'f') {
5024 } else {
5025 return MG_SSL_ERROR;
5026 }
5030 }
5031 key_len++;
5032 DBG((
"identity = '%s', key = (%u)", identity, (
unsigned int) key_len));
5033 ctx->identity_len = strlen(identity);
5034 mbuf_append(&ctx->psk, identity, ctx->identity_len + 1);
5036 SSL_CTX_set_psk_client_callback(ctx->ssl_ctx, mg_ssl_if_ossl_psk_cb);
5037 SSL_CTX_set_app_data(ctx->ssl_ctx, ctx);
5038 return MG_SSL_OK;
5039}
5040#else
5041static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(struct mg_ssl_if_ctx *ctx,
5042 const char *identity,
5043 const char *key_str) {
5044 (void) ctx;
5045 (void) identity;
5046 (void) key_str;
5047
5048 return MG_SSL_ERROR;
5049}
5050#endif
5051
5053 const char *ca_cert) {
5054 const char *err_msg = NULL;
5055 struct mg_ssl_if_conn_params params;
5056 memset(¶ms, 0, sizeof(params));
5057 params.cert = cert;
5058 params.ca_cert = ca_cert;
5059 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
5060 return err_msg;
5061 }
5062 return NULL;
5063}
5064
5065#endif
5066#ifdef MG_MODULE_LINES
5067#line 1 "mongoose/src/mg_ssl_if_mbedtls.c"
5068#endif
5069
5070
5071
5072
5073
5074#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_MBEDTLS
5075
5076#include <mbedtls/debug.h>
5077#include <mbedtls/ecp.h>
5078#include <mbedtls/net.h>
5079#include <mbedtls/platform.h>
5080#include <mbedtls/ssl.h>
5081#include <mbedtls/ssl_internal.h>
5082#include <mbedtls/x509_crt.h>
5083#include <mbedtls/version.h>
5084
5085static void mg_ssl_mbed_log(
void *ctx,
int level,
const char *
file,
int line,
5088 switch (level) {
5089 case 1:
5091 break;
5092 case 2:
5094 break;
5095 case 3:
5097 break;
5098 default:
5100 }
5101
5102 LOG(cs_level, (
"%p %.*s", ctx, (
int) (strlen(
str) - 1),
str));
5103 (void) ctx;
5106 (void) line;
5107 (void) cs_level;
5108}
5109
5110struct mg_ssl_if_ctx {
5111 mbedtls_ssl_config *conf;
5112 mbedtls_ssl_context *ssl;
5113 mbedtls_x509_crt *cert;
5114 mbedtls_pk_context *
key;
5115 mbedtls_x509_crt *ca_cert;
5116 struct mbuf cipher_suites;
5117 size_t saved_len;
5118};
5119
5120
5121extern int mg_ssl_if_mbed_random(
void *ctx,
unsigned char *
buf,
size_t len);
5122
5123void mg_ssl_if_init() {
5124 LOG(
LL_INFO, (
"%s", MBEDTLS_VERSION_STRING_FULL));
5125}
5126
5127enum mg_ssl_if_result mg_ssl_if_conn_accept(
struct mg_connection *nc,
5129 struct mg_ssl_if_ctx *ctx =
5130 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
5131 struct mg_ssl_if_ctx *lc_ctx = (struct mg_ssl_if_ctx *) lc->ssl_if_data;
5132 nc->ssl_if_data = ctx;
5133 if (ctx == NULL || lc_ctx == NULL) return MG_SSL_ERROR;
5134 ctx->ssl = (mbedtls_ssl_context *)
MG_CALLOC(1,
sizeof(*ctx->ssl));
5135 if (mbedtls_ssl_setup(ctx->ssl, lc_ctx->conf) != 0) {
5136 return MG_SSL_ERROR;
5137 }
5138 return MG_SSL_OK;
5139}
5140
5141static enum mg_ssl_if_result mg_use_cert(struct mg_ssl_if_ctx *ctx,
5142 const char *cert,
const char *
key,
5143 const char **err_msg);
5144static enum mg_ssl_if_result mg_use_ca_cert(struct mg_ssl_if_ctx *ctx,
5145 const char *cert);
5146static enum mg_ssl_if_result mg_set_cipher_list(struct mg_ssl_if_ctx *ctx,
5147 const char *ciphers);
5148#ifdef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
5149static enum mg_ssl_if_result mg_ssl_if_mbed_set_psk(struct mg_ssl_if_ctx *ctx,
5150 const char *identity,
5152#endif
5153
5154enum mg_ssl_if_result mg_ssl_if_conn_init(
5155 struct mg_connection *nc,
const struct mg_ssl_if_conn_params *params,
5156 const char **err_msg) {
5157 struct mg_ssl_if_ctx *ctx =
5158 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
5159 DBG((
"%p %s,%s,%s", nc, (params->cert ? params->cert :
""),
5160 (params->
key ? params->
key :
""),
5161 (params->ca_cert ? params->ca_cert : "")));
5162
5163 if (ctx == NULL) {
5165 return MG_SSL_ERROR;
5166 }
5167 nc->ssl_if_data = ctx;
5168 ctx->conf = (mbedtls_ssl_config *)
MG_CALLOC(1,
sizeof(*ctx->conf));
5170 mbedtls_ssl_config_init(ctx->conf);
5171 mbedtls_ssl_conf_dbg(ctx->conf, mg_ssl_mbed_log, nc);
5172 if (mbedtls_ssl_config_defaults(
5174 : MBEDTLS_SSL_IS_CLIENT),
5175 MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
5177 return MG_SSL_ERROR;
5178 }
5179
5180
5181 mbedtls_ssl_conf_min_version(ctx->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
5182 MBEDTLS_SSL_MINOR_VERSION_3);
5183 mbedtls_ssl_conf_rng(ctx->conf, mg_ssl_if_mbed_random, nc);
5184
5185 if (params->cert != NULL &&
5186 mg_use_cert(ctx, params->cert, params->key, err_msg) != MG_SSL_OK) {
5187 return MG_SSL_ERROR;
5188 }
5189
5190 if (params->ca_cert != NULL &&
5191 mg_use_ca_cert(ctx, params->ca_cert) != MG_SSL_OK) {
5193 return MG_SSL_ERROR;
5194 }
5195
5196 if (mg_set_cipher_list(ctx, params->cipher_suites) != MG_SSL_OK) {
5198 return MG_SSL_ERROR;
5199 }
5200
5201#ifdef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
5202 if (mg_ssl_if_mbed_set_psk(ctx, params->psk_identity, params->psk_key) !=
5203 MG_SSL_OK) {
5205 return MG_SSL_ERROR;
5206 }
5207#endif
5208
5210 ctx->ssl = (mbedtls_ssl_context *)
MG_CALLOC(1,
sizeof(*ctx->ssl));
5211 mbedtls_ssl_init(ctx->ssl);
5212 if (mbedtls_ssl_setup(ctx->ssl, ctx->conf) != 0) {
5214 return MG_SSL_ERROR;
5215 }
5216 if (params->server_name != NULL &&
5217 mbedtls_ssl_set_hostname(ctx->ssl, params->server_name) != 0) {
5218 return MG_SSL_ERROR;
5219 }
5220 }
5221
5222#ifdef MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN
5223 if (mbedtls_ssl_conf_max_frag_len(ctx->conf,
5224#if MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 512
5225 MBEDTLS_SSL_MAX_FRAG_LEN_512
5226#elif MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 1024
5227 MBEDTLS_SSL_MAX_FRAG_LEN_1024
5228#elif MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 2048
5229 MBEDTLS_SSL_MAX_FRAG_LEN_2048
5230#elif MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 4096
5231 MBEDTLS_SSL_MAX_FRAG_LEN_4096
5232#else
5233#error Invalid MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN
5234#endif
5235 ) != 0) {
5236 return MG_SSL_ERROR;
5237 }
5238#endif
5239
5241
5242 return MG_SSL_OK;
5243}
5244
5245static int mg_ssl_if_mbed_send(void *ctx, const unsigned char *buf,
5246 size_t len) {
5249 if (
n > 0)
return n;
5250 if (
n == 0)
return MBEDTLS_ERR_SSL_WANT_WRITE;
5251 return MBEDTLS_ERR_NET_SEND_FAILED;
5252}
5253
5254static int mg_ssl_if_mbed_recv(
void *
ctx,
unsigned char *
buf,
size_t len) {
5257 if (
n > 0)
return n;
5258 if (
n == 0)
return MBEDTLS_ERR_SSL_WANT_READ;
5259 return MBEDTLS_ERR_NET_RECV_FAILED;
5260}
5261
5262static enum mg_ssl_if_result mg_ssl_if_mbed_err(
struct mg_connection *nc,
5263 int ret) {
5264 enum mg_ssl_if_result res = MG_SSL_OK;
5265 if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
5266 res = MG_SSL_WANT_READ;
5267 } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
5268 res = MG_SSL_WANT_WRITE;
5269 } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
5270 LOG(
LL_DEBUG, (
"%p TLS connection closed by peer", nc));
5272 res = MG_SSL_OK;
5273 } else if (ret == MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) {
5275 res = MG_SSL_ERROR;
5276 } else if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
5278 res = MG_SSL_ERROR;
5279 } else if (ret == MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) {
5281 res = MG_SSL_ERROR;
5282 } else if (ret == MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) {
5284 res = MG_SSL_ERROR;
5285 } else if (ret == MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) {
5287 res = MG_SSL_ERROR;
5288 } else if (ret == MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) {
5290 res = MG_SSL_ERROR;
5291 } else if (ret == MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) {
5293 res = MG_SSL_ERROR;
5294 } else if (ret == MBEDTLS_ERR_NET_RECV_FAILED) {
5296 res = MG_SSL_ERROR;
5297 } else {
5298 LOG(
LL_ERROR, (
"%p mbedTLS error: -0x%04x", nc, -ret));
5300 res = MG_SSL_ERROR;
5301 }
5303 return res;
5304}
5305
5306static void mg_ssl_if_mbed_free_certs_and_keys(
struct mg_ssl_if_ctx *
ctx) {
5307 if (
ctx->cert != NULL) {
5308 mbedtls_x509_crt_free(
ctx->cert);
5311 mbedtls_pk_free(
ctx->key);
5314 }
5315 if (
ctx->ca_cert != NULL) {
5316 mbedtls_ssl_conf_ca_chain(
ctx->conf, NULL, NULL);
5317#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
5318 if (
ctx->conf->ca_chain_file != NULL) {
5320 ctx->conf->ca_chain_file = NULL;
5321 }
5322#endif
5323 mbedtls_x509_crt_free(
ctx->ca_cert);
5325 ctx->ca_cert = NULL;
5326 }
5327}
5328
5329enum mg_ssl_if_result mg_ssl_if_handshake(
struct mg_connection *nc) {
5330 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
5331 int err;
5332
5333 if (ctx->ssl->p_bio == NULL) {
5334 mbedtls_ssl_set_bio(ctx->ssl, nc, mg_ssl_if_mbed_send, mg_ssl_if_mbed_recv,
5335 NULL);
5336 }
5337 err = mbedtls_ssl_handshake(ctx->ssl);
5338 if (err != 0) return mg_ssl_if_mbed_err(nc, err);
5339#ifdef MG_SSL_IF_MBEDTLS_FREE_CERTS
5340
5341
5342
5343
5344 mbedtls_x509_crt_free(ctx->ssl->session->peer_cert);
5345 mbedtls_free(ctx->ssl->session->peer_cert);
5346 ctx->ssl->session->peer_cert = NULL;
5347
5349 if (ctx->conf->key_cert != NULL) {
5350
5352 ctx->conf->key_cert = NULL;
5353 }
5354 mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL);
5355 mg_ssl_if_mbed_free_certs_and_keys(ctx);
5356 }
5357#endif
5358 return MG_SSL_OK;
5359}
5360
5361int mg_ssl_if_read(
struct mg_connection *nc,
void *buf,
size_t len) {
5362 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
5363 int n = mbedtls_ssl_read(ctx->ssl, (
unsigned char *) buf, len);
5364 DBG((
"%p %d -> %d", nc, (
int) len,
n));
5365 if (
n < 0)
return mg_ssl_if_mbed_err(nc,
n);
5368}
5369
5370int mg_ssl_if_write(
struct mg_connection *nc,
const void *buf,
size_t len) {
5371 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
5372
5373
5374
5375
5376
5377
5378 size_t l = len;
5379 if (ctx->saved_len > 0 && ctx->saved_len < l) l = ctx->saved_len;
5380 int n = mbedtls_ssl_write(ctx->ssl, (
const unsigned char *) buf, l);
5381 DBG((
"%p %d,%d,%d -> %d", nc, (
int) len, (
int) ctx->saved_len, (
int) l,
n));
5383 if (
n == MBEDTLS_ERR_SSL_WANT_READ ||
n == MBEDTLS_ERR_SSL_WANT_WRITE) {
5384 ctx->saved_len = len;
5385 }
5386 return mg_ssl_if_mbed_err(nc,
n);
5388 ctx->saved_len = 0;
5389 }
5391}
5392
5394 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
5395 if (ctx == NULL) return;
5396 mbedtls_ssl_close_notify(ctx->ssl);
5397}
5398
5400 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
5401 if (ctx == NULL) return;
5402 nc->ssl_if_data = NULL;
5403 if (ctx->ssl != NULL) {
5404 mbedtls_ssl_free(ctx->ssl);
5406 }
5407 mg_ssl_if_mbed_free_certs_and_keys(ctx);
5408 if (ctx->conf != NULL) {
5409 mbedtls_ssl_config_free(ctx->conf);
5411 }
5413 memset(ctx, 0, sizeof(*ctx));
5415}
5416
5417static enum mg_ssl_if_result mg_use_ca_cert(struct mg_ssl_if_ctx *ctx,
5418 const char *ca_cert) {
5419 if (ca_cert == NULL || strcmp(ca_cert, "*") == 0) {
5420 mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_NONE);
5421 return MG_SSL_OK;
5422 }
5423 ctx->ca_cert = (mbedtls_x509_crt *)
MG_CALLOC(1,
sizeof(*ctx->ca_cert));
5424 mbedtls_x509_crt_init(ctx->ca_cert);
5425#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
5426 ca_cert = strdup(ca_cert);
5427 mbedtls_ssl_conf_ca_chain_file(ctx->conf, ca_cert, NULL);
5428#else
5429 if (mbedtls_x509_crt_parse_file(ctx->ca_cert, ca_cert) != 0) {
5430 return MG_SSL_ERROR;
5431 }
5432 mbedtls_ssl_conf_ca_chain(ctx->conf, ctx->ca_cert, NULL);
5433#endif
5434 mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
5435 return MG_SSL_OK;
5436}
5437
5438static enum mg_ssl_if_result mg_use_cert(struct mg_ssl_if_ctx *ctx,
5439 const char *cert,
const char *
key,
5440 const char **err_msg) {
5441 if (
key == NULL)
key = cert;
5442 if (cert == NULL || cert[0] ==
'\0' ||
key == NULL ||
key[0] ==
'\0') {
5443 return MG_SSL_OK;
5444 }
5445 ctx->cert = (mbedtls_x509_crt *)
MG_CALLOC(1,
sizeof(*ctx->cert));
5446 mbedtls_x509_crt_init(ctx->cert);
5447 ctx->key = (mbedtls_pk_context *)
MG_CALLOC(1,
sizeof(*ctx->key));
5448 mbedtls_pk_init(ctx->key);
5449 if (mbedtls_x509_crt_parse_file(ctx->cert, cert) != 0) {
5451 return MG_SSL_ERROR;
5452 }
5453 if (mbedtls_pk_parse_keyfile(ctx->key,
key, NULL) != 0) {
5455 return MG_SSL_ERROR;
5456 }
5457 if (mbedtls_ssl_conf_own_cert(ctx->conf, ctx->cert, ctx->key) != 0) {
5459 return MG_SSL_ERROR;
5460 }
5461 return MG_SSL_OK;
5462}
5463
5464static const int mg_s_cipher_list[] = {
5465#if CS_PLATFORM != CS_P_ESP8266
5466 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
5467 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
5468 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
5469 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
5470 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
5471 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
5472 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
5473 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
5474 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
5475 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
5476 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
5477 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
5478 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
5479 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
5480 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
5481#else
5482
5483
5484
5485
5486
5487 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
5488 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
5489 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
5490 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
5491 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
5492 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
5493 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
5494 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
5495 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
5496 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
5497 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
5498 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
5499 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
5500#endif
5501 0,
5502};
5503
5504
5505
5506
5507
5508
5509
5510static enum mg_ssl_if_result mg_set_cipher_list(struct mg_ssl_if_ctx *ctx,
5511 const char *ciphers) {
5512 if (ciphers != NULL) {
5513 int l, id;
5514 const char *s = ciphers, *
e;
5515 char tmp[50];
5516 while (s != NULL) {
5518 l = (
e != NULL ? (
e - s) : (int) strlen(s));
5519 strncpy(tmp, s, l);
5520 tmp[l] = '\0';
5521 id = mbedtls_ssl_get_ciphersuite_id(tmp);
5522 DBG((
"%s -> %04x", tmp,
id));
5523 if (id != 0) {
5524 mbuf_append(&ctx->cipher_suites, &
id,
sizeof(
id));
5525 }
5526 s = (
e != NULL ?
e + 1 : NULL);
5527 }
5528 if (ctx->cipher_suites.len == 0) return MG_SSL_ERROR;
5529 id = 0;
5530 mbuf_append(&ctx->cipher_suites, &
id,
sizeof(
id));
5532 mbedtls_ssl_conf_ciphersuites(ctx->conf,
5533 (const int *) ctx->cipher_suites.buf);
5534 } else {
5535 mbedtls_ssl_conf_ciphersuites(ctx->conf, mg_s_cipher_list);
5536 }
5537 return MG_SSL_OK;
5538}
5539
5540#ifdef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
5541static enum mg_ssl_if_result mg_ssl_if_mbed_set_psk(struct mg_ssl_if_ctx *ctx,
5542 const char *identity,
5543 const char *key_str) {
5544 unsigned char key[32];
5545 size_t key_len;
5546 if (identity == NULL && key_str == NULL) return MG_SSL_OK;
5547 if (identity == NULL || key_str == NULL) return MG_SSL_ERROR;
5548 key_len = strlen(key_str);
5549 if (key_len != 32 && key_len != 64) return MG_SSL_ERROR;
5551 memset(
key, 0,
sizeof(
key));
5552 key_len = 0;
5553 for (
i = 0; key_str[
i] !=
'\0';
i++) {
5555 char hc = tolower((
int) key_str[
i]);
5556 if (hc >= '0' && hc <= '9') {
5558 } else if (hc >= 'a' && hc <= 'f') {
5560 } else {
5561 return MG_SSL_ERROR;
5562 }
5566 }
5567 key_len++;
5568 DBG((
"identity = '%s', key = (%u)", identity, (
unsigned int) key_len));
5569
5570 if (mbedtls_ssl_conf_psk(ctx->conf, (
const unsigned char *)
key, key_len,
5571 (const unsigned char *) identity,
5572 strlen(identity)) != 0) {
5573 return MG_SSL_ERROR;
5574 }
5575 return MG_SSL_OK;
5576}
5577#endif
5578
5580 const char *ca_cert) {
5581 const char *err_msg = NULL;
5582 struct mg_ssl_if_conn_params params;
5583 memset(¶ms, 0, sizeof(params));
5584 params.cert = cert;
5585 params.ca_cert = ca_cert;
5586 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
5587 return err_msg;
5588 }
5589 return NULL;
5590}
5591
5592
5593#ifdef MG_SSL_MBED_DUMMY_RANDOM
5594int mg_ssl_if_mbed_random(void *ctx, unsigned char *buf, size_t len) {
5595 (void) ctx;
5596 while (len--) *buf++ = rand();
5597 return 0;
5598}
5599#endif
5600
5601#endif
5602#ifdef MG_MODULE_LINES
5603#line 1 "mongoose/src/mg_uri.c"
5604#endif
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5620 const char *seps,
struct mg_str *res) {
5623 for (; *p <
end; (*p)++) {
5624 for (
q = seps; *
q !=
'\0';
q++) {
5625 if (**p == *
q)
break;
5626 }
5627 if (*
q !=
'\0')
break;
5628 }
5629 res->
len = (*p) - res->
p;
5630 if (*p <
end) (*p)++;
5631}
5632
5635 unsigned int *port,
struct mg_str *path,
struct mg_str *query,
5636 struct mg_str *fragment) {
5637 struct mg_str rscheme = {0, 0}, ruser_info = {0, 0}, rhost = {0, 0},
5638 rpath = {0, 0}, rquery = {0, 0}, rfragment = {0, 0};
5639 unsigned int rport = 0;
5640 enum {
5641 P_START,
5642 P_SCHEME_OR_PORT,
5643 P_USER_INFO,
5644 P_HOST,
5645 P_PORT,
5646 P_REST
5648
5649 const char *
p = uri.
p, *
end =
p + uri.
len;
5652 case P_START:
5653
5654
5655
5656
5657
5658
5659
5662 break;
5663 }
5664 for (;
p <
end;
p++) {
5666 state = P_SCHEME_OR_PORT;
5667 break;
5668 }
else if (*
p ==
'/') {
5670 break;
5671 }
5672 }
5675 rhost.len =
p - uri.
p;
5676 }
5677 break;
5678 case P_SCHEME_OR_PORT:
5679 if (
end -
p >= 3 && strncmp(
p,
"://", 3) == 0) {
5681 rscheme.
len =
p - uri.
p;
5682 state = P_USER_INFO;
5684 } else {
5686 rhost.len =
p - uri.
p;
5688 }
5689 break;
5690 case P_USER_INFO:
5692 for (;
p <
end;
p++) {
5693 if (*
p ==
'@' || *
p ==
'[' || *
p ==
'/') {
5694 break;
5695 }
5696 }
5697 if (
p ==
end || *
p ==
'/' || *
p ==
'[') {
5698
5700 }
5701 ruser_info.len =
p - ruser_info.p;
5703 break;
5704 case P_HOST:
5708 int found = 0;
5709 for (; !found &&
p <
end;
p++) {
5710 found = (*
p ==
']');
5711 }
5712 if (!found) return -1;
5713 } else {
5714 for (;
p <
end;
p++) {
5715 if (*
p ==
':' || *
p ==
'/')
break;
5716 }
5717 }
5718 rhost.len =
p - rhost.p;
5722 break;
5723 }
else if (*
p ==
'/') {
5725 break;
5726 }
5727 }
5728 break;
5729 case P_PORT:
5731 for (;
p <
end;
p++) {
5734 break;
5735 }
5736 rport *= 10;
5738 }
5739 break;
5740 case P_REST:
5741
5743 if (
p <
end && *(
p - 1) ==
'?') {
5745 }
5747 break;
5748 }
5749 }
5750
5751 if (scheme != 0) *scheme = rscheme;
5752 if (user_info != 0) *user_info = ruser_info;
5753 if (host != 0) *host = rhost;
5754 if (port != 0) *port = rport;
5755 if (path != 0) *path = rpath;
5756 if (query != 0) *query = rquery;
5757 if (fragment != 0) *fragment = rfragment;
5758
5759 return 0;
5760}
5761
5762
5764 const char *s = in->
p, *se = s + in->
len;
5765 char *cp = (
char *) out->
p, *
d;
5766
5767 if (in->len == 0 || *s != '/') {
5768 out->len = 0;
5769 return 0;
5770 }
5771
5773
5774 while (s < se) {
5775 const char *next = s;
5778 if (
mg_vcmp(&component,
".") == 0) {
5779
5780 }
else if (
mg_vcmp(&component,
"..") == 0) {
5781
5782 if (
d > cp + 1 && *(
d - 1) ==
'/')
d--;
5783 while (
d > cp && *(
d - 1) !=
'/')
d--;
5784 } else {
5785 memmove(
d, s, next - s);
5787 }
5788 s = next;
5789 }
5790 if (
d == cp) *
d++ =
'/';
5791
5792 out->p = cp;
5794 return 1;
5795}
5796
5798 const struct mg_str *host,
unsigned int port,
5800 const struct mg_str *fragment,
int normalize_path,
5802 int result = -1;
5805
5806 if (scheme != NULL && scheme->
len > 0) {
5809 }
5810
5811 if (user_info != NULL && user_info->
len > 0) {
5814 }
5815
5816 if (host != NULL && host->
len > 0) {
5818 }
5819
5820 if (port != 0) {
5821 char port_str[20];
5822 int port_str_len = sprintf(port_str, ":%u", port);
5824 }
5825
5826 if (path != NULL && path->
len > 0) {
5827 if (normalize_path) {
5829 if (npath.
len != path->
len)
goto out;
5831 free((
void *) npath.
p);
5832 goto out;
5833 }
5835 free((
void *) npath.
p);
5836 } else {
5838 }
5839 } else if (normalize_path) {
5841 }
5842
5843 if (query != NULL && query->
len > 0) {
5846 }
5847
5848 if (fragment != NULL && fragment->
len > 0) {
5851 }
5852
5853 result = 0;
5854
5855out:
5856 if (result == 0) {
5859 } else {
5863 }
5864 return result;
5865}
5866#ifdef MG_MODULE_LINES
5867#line 1 "mongoose/src/mg_http.c"
5868#endif
5869
5870
5871
5872
5873
5874#if MG_ENABLE_HTTP
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886struct altbuf {
5888 char *user_buf;
5889 size_t len;
5890 size_t user_buf_size;
5891};
5892
5893
5894
5895
5896MG_INTERNAL void altbuf_init(
struct altbuf *ab,
char *
buf,
size_t buf_size) {
5899 ab->user_buf_size = buf_size;
5900 ab->len = 0;
5901}
5902
5903
5904
5905
5906MG_INTERNAL void altbuf_append(
struct altbuf *ab,
char c) {
5907 if (ab->len < ab->user_buf_size) {
5908
5909 ab->user_buf[ab->len++] =
c;
5910 } else {
5911
5912
5913
5914
5915
5916
5917
5918 if (ab->len > 0 && ab->m.len == 0) {
5920 }
5921
5923 ab->len = ab->m.len;
5924 }
5925}
5926
5927
5928
5929
5932 ab->len = 0;
5933}
5934
5935
5936
5937
5938
5939MG_INTERNAL int altbuf_reallocated(
struct altbuf *ab) {
5940 return ab->len > ab->user_buf_size;
5941}
5942
5943
5944
5945
5946
5947MG_INTERNAL char *altbuf_get_buf(
struct altbuf *ab,
int trim) {
5948 if (altbuf_reallocated(ab)) {
5949 if (trim) {
5951 }
5952 return ab->m.buf;
5953 } else {
5954 return ab->user_buf;
5955 }
5956}
5957
5958
5959
5960static const char *mg_version_header =
"Mongoose/" MG_VERSION;
5961
5963
5968 int keepalive;
5970};
5971
5972#if MG_ENABLE_HTTP_CGI
5975};
5976#endif
5977
5980};
5981
5984 struct mg_str uri_pattern;
5985 char *auth_domain;
5986 char *auth_file;
5987
5989#if MG_ENABLE_CALLBACK_USERDATA
5990 void *user_data;
5991#endif
5992};
5993
6001};
6002
6011 int data_avail;
6012};
6013
6014struct mg_reverse_proxy_data {
6016};
6017
6018struct mg_ws_proto_data {
6019
6020
6021
6022
6023
6024
6025 size_t reass_len;
6026};
6027
6029#if MG_ENABLE_FILESYSTEM
6031#endif
6032#if MG_ENABLE_HTTP_CGI
6034#endif
6035#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6037#endif
6038#if MG_ENABLE_HTTP_WEBSOCKET
6039 struct mg_ws_proto_data ws_data;
6040#endif
6044 struct mg_reverse_proxy_data reverse_proxy_data;
6045 size_t rcvd;
6046};
6047
6048static void mg_http_proto_data_destructor(void *proto_data);
6049
6052 struct mg_connect_opts opts,
const char *scheme1,
const char *scheme2,
6053 const char *scheme_ssl1, const char *scheme_ssl2, const char *url,
6055
6058
6059 if (
c->proto_data != NULL) {
6060 void *pd =
c->proto_data;
6061 c->proto_data = NULL;
6062 mg_http_proto_data_destructor(pd);
6063 }
6065 c->proto_data_destructor = mg_http_proto_data_destructor;
6067}
6068
6072}
6073
6074#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6075static void mg_http_free_proto_data_mp_stream(
6080 memset(mp, 0, sizeof(*mp));
6081}
6082#endif
6083
6084#if MG_ENABLE_FILESYSTEM
6087 if (
d->fp != NULL) {
6089 }
6091 }
6092}
6093#endif
6094
6097
6098 while (current != NULL) {
6100 MG_FREE((
void *) current->uri_pattern.p);
6101 MG_FREE((
void *) current->auth_domain);
6102 MG_FREE((
void *) current->auth_file);
6104 current = tmp;
6105 }
6106
6107 ep = NULL;
6108}
6109
6110static void mg_http_free_reverse_proxy_data(struct mg_reverse_proxy_data *rpd) {
6111 if (rpd->linked_conn != NULL) {
6112
6113
6114
6115
6116
6118 if (pd->reverse_proxy_data.linked_conn != NULL) {
6120 pd->reverse_proxy_data.linked_conn = NULL;
6121 }
6122 rpd->linked_conn = NULL;
6123 }
6124}
6125
6126static void mg_http_proto_data_destructor(void *proto_data) {
6128#if MG_ENABLE_FILESYSTEM
6130#endif
6131#if MG_ENABLE_HTTP_CGI
6133#endif
6134#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6135 mg_http_free_proto_data_mp_stream(&pd->mp_stream);
6136#endif
6138 mg_http_free_reverse_proxy_data(&pd->reverse_proxy_data);
6140}
6141
6142#if MG_ENABLE_FILESYSTEM
6143
6144#define MIME_ENTRY(_ext, _type) \
6145 { _ext, sizeof(_ext) - 1, _type }
6146static const struct {
6157 MIME_ENTRY(
"js",
"application/x-javascript"),
6165 MIME_ENTRY(
"torrent",
"application/x-bittorrent"),
6179 MIME_ENTRY(
"exe",
"application/octet-stream"),
6180 MIME_ENTRY(
"zip",
"application/x-zip-compressed"),
6185 MIME_ENTRY(
"arj",
"application/x-arj-compressed"),
6186 MIME_ENTRY(
"rar",
"application/x-rar-compressed"),
6189 MIME_ENTRY(
"swf",
"application/x-shockwave-flash"),
6199 {NULL, 0, NULL}};
6200
6203 const char *ext, *overrides;
6206
6207 path_len = strlen(path);
6208
6209 overrides = opts->custom_mime_types;
6211 ext = path + (path_len -
k.len);
6213 return v;
6214 }
6215 }
6216
6222 r.len = strlen(r.p);
6223 return r;
6224 }
6225 }
6226
6227 r.p = dflt;
6228 r.len = strlen(r.p);
6229 return r;
6230}
6231#endif
6232
6233
6234
6235
6236
6237
6238
6240 const unsigned char *buf = (unsigned char *) s;
6242
6243 for (
i = 0;
i < buf_len;
i++) {
6244 if (!isprint(buf[
i]) && buf[
i] !=
'\r' && buf[
i] !=
'\n' && buf[
i] < 128) {
6245 return -1;
6246 }
else if (buf[
i] ==
'\n' &&
i + 1 < buf_len && buf[
i + 1] ==
'\n') {
6248 }
else if (buf[
i] ==
'\n' &&
i + 2 < buf_len && buf[
i + 1] ==
'\r' &&
6249 buf[
i + 2] ==
'\n') {
6251 }
6252 }
6253
6254 return 0;
6255}
6256
6262
6265
6266 while (v->len > 0 && v->p[v->len - 1] == ' ') {
6267 v->len--;
6268 }
6269
6270
6271
6272
6273
6274
6275 if (
k->len != 0 && v->len == 0) {
6276 continue;
6277 }
6278
6279 if (
k->len == 0 || v->len == 0) {
6281 k->len = v->len = 0;
6282 break;
6283 }
6284
6286 req->
body.
len = (size_t) to64(v->p);
6288 }
6289
6291 }
6292
6293 return s;
6294}
6295
6297 const char *
end, *qs;
6299
6300 if (
len <= 0)
return len;
6301
6302 memset(hm, 0, sizeof(*hm));
6307
6308
6309 while (s <
end && isspace(*(
unsigned char *) s)) s++;
6310
6311 if (is_req) {
6312
6317
6318
6319 if ((qs = (
char *) memchr(hm->
uri.
p,
'?', hm->
uri.
len)) != NULL) {
6323 }
6324 } else {
6326 if (
end - s < 4 || s[0] <
'0' || s[0] >
'9' || s[3] !=
' ')
return -1;
6329 s += 4;
6331 }
6332
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350 if (hm->
body.
len == (
size_t) ~0 && is_req &&
6355 }
6356
6358}
6359
6362
6366 return v;
6367 }
6368
6369 return NULL;
6370}
6371
6372#if MG_ENABLE_FILESYSTEM
6377
6381 to_read = 0;
6382 } else {
6384 }
6385 if (to_read >
left) {
6387 }
6388 if (to_read > 0) {
6393 DBG((
"%p sent %d (total %d)", nc, (
int)
n, (
int) pd->
file.
sent));
6394 }
6395 } else {
6396
6397 }
6400 pd->
file.keepalive));
6403 }
6407 size_t n = mg_fwrite(io->
buf, 1, to_write, pd->
file.
fp);
6411 }
6415 }
6416 }
6417#if MG_ENABLE_HTTP_CGI
6419
6422 } else {
6424 }
6425 }
6426#endif
6427}
6428#endif
6429
6430
6431
6432
6433
6434
6436 size_t *chunk_len) {
6437 unsigned char *s = (
unsigned char *)
buf;
6440
6441
6442 while (
i <
len && isxdigit(s[
i])) {
6444 n += (s[
i] >=
'0' && s[
i] <=
'9') ? s[
i] -
'0' : tolower(s[
i]) -
'a' + 10;
6447
6448 return 0;
6449 }
6450 }
6451
6452
6453 if (
i == 0 ||
i + 2 >
len || s[
i] !=
'\r' || s[
i + 1] !=
'\n') {
6454 return 0;
6455 }
6457
6458
6459 *chunk_data = (
char *) s +
i;
6461
6462
6464
6465
6466 if (
i == 0 ||
i + 2 >
len || s[
i] !=
'\r' || s[
i + 1] !=
'\n') {
6467 return 0;
6468 }
6470}
6471
6474 size_t blen) {
6477 size_t i,
n, data_len, body_len, zero_chunk_received = 0;
6478
6480 assert(blen >= body_len);
6481
6482
6486
6487 memmove(buf + body_len,
data, data_len);
6488 body_len += data_len;
6490
6491 if (data_len == 0) {
6492 zero_chunk_received = 1;
6494 break;
6495 }
6496 }
6497
6499
6501 memmove(buf + body_len, buf +
i, blen -
i);
6502 memset(buf + body_len + blen -
i, 0,
i - body_len);
6505
6506
6507 nc->
flags &= ~MG_F_DELETE_CHUNK;
6509
6510
6512 memset(buf, 0, body_len);
6513 memmove(buf, buf + body_len, blen -
i);
6517 }
6518
6519 if (zero_chunk_received) {
6520
6523 }
6524 }
6525
6526 return body_len;
6527}
6528
6530 struct mg_str *uri_path) {
6533 int matched, matched_max = 0;
6535
6536 if (nc == NULL) return NULL;
6537
6539
6540 if (pd == NULL) return NULL;
6541
6543 while (ep != NULL) {
6545 if (matched > matched_max) {
6546
6547 ret = ep;
6548 matched_max = matched;
6549 }
6550 }
6551
6553 }
6554
6555 return ret;
6556}
6557
6558#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6559static void mg_http_multipart_continue(
struct mg_connection *nc);
6560
6561static void mg_http_multipart_begin(
struct mg_connection *nc,
6563
6564#endif
6565
6568
6570 int req_len) {
6571
6572 hm->
body.
len =
c->recv_mbuf.len - req_len;
6573 c->flags &= ~MG_F_DELETE_CHUNK;
6575
6577}
6578
6579
6580
6581
6582
6583
6584#ifdef __xtensa__
6585static void mg_http_handler2(
struct mg_connection *nc,
int ev,
6586 void *ev_data
MG_UD_ARG(
void *user_data),
6588
6590 void *ev_data
MG_UD_ARG(
void *user_data)) {
6592 mg_http_handler2(nc, ev, ev_data
MG_UD_ARG(user_data), &hm);
6593}
6594
6595static void mg_http_handler2(
struct mg_connection *nc,
int ev,
6596 void *ev_data
MG_UD_ARG(
void *user_data),
6598#else
6600 void *ev_data
MG_UD_ARG(
void *user_data)) {
6602#endif
6605 int req_len;
6606 const int is_req = (nc->
listener != NULL);
6607#if MG_ENABLE_HTTP_WEBSOCKET
6609#endif
6611#if MG_ENABLE_HTTP_CGI
6612
6613 if (pd != NULL && pd->
cgi.
cgi_nc != NULL) {
6616 }
6617#endif
6618#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6619 if (pd != NULL && pd->mp_stream.boundary != NULL) {
6620
6621
6622
6623
6625 memset(&mp, 0, sizeof(mp));
6626 mp.status = -1;
6628 mp.
var_name = pd->mp_stream.var_name;
6631 nc->
user_data, MG_EV_HTTP_PART_END, &mp);
6635 nc->
user_data, MG_EV_HTTP_MULTIPART_REQUEST_END, &mp);
6636 } else
6637#endif
6640
6641
6642
6643
6647 deliver_chunk(nc, hm, req_len);
6649 }
6653 }
6654 }
6655
6656#if MG_ENABLE_FILESYSTEM
6657 if (pd != NULL && pd->
file.
fp != NULL) {
6659 }
6660#endif
6661
6663
6664#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6665 if (pd != NULL && pd->mp_stream.boundary != NULL &&
6668 pd->rcvd += *(int *) ev_data;
6669 mg_http_multipart_continue(nc);
6670 } else if (pd->mp_stream.data_avail) {
6671
6672 mg_http_multipart_continue(nc);
6673 }
6674 return;
6675 }
6676#endif
6677
6680
6681 again:
6683
6684 if (req_len > 0) {
6685
6686 if (!pd) {
6687 pd = mg_http_create_proto_data(nc);
6688 }
6690 }
6691
6692 if (req_len > 0 &&
6696 }
6697
6698#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6700 s->
len >= 9 && strncmp(s->
p,
"multipart", 9) == 0) {
6701 mg_http_multipart_begin(nc, hm, req_len);
6702 mg_http_multipart_continue(nc);
6703 return;
6704 }
6705#endif
6706
6707
6708 if ((req_len < 0 ||
6710 DBG((
"invalid request"));
6712 } else if (req_len == 0) {
6713
6714 }
6715#if MG_ENABLE_HTTP_WEBSOCKET
6717
6718 DBG((
"%p WebSocket upgrade code %d", nc, hm->
resp_code));
6721
6723 hm);
6727 } else {
6729 hm);
6732 }
6736
6737
6741
6742
6743
6744
6745
6746
6748 if (ep != NULL) {
6750#if MG_ENABLE_CALLBACK_USERDATA
6752#endif
6753 }
6754
6755
6757 hm);
6761 }
6763 hm);
6765 }
6766 }
6767#endif
6769
6770 deliver_chunk(nc, hm, req_len);
6772 LOG(
LL_ERROR, (
"%p recv buffer (%lu bytes) exceeds the limit "
6773 "%lu bytes, and not drained, closing",
6777 }
6778 } else {
6779
6780 int request_done = 1;
6787 deliver_chunk(nc, hm, req_len);
6788
6792#if MG_ENABLE_FILESYSTEM
6793
6794
6795
6796
6797 if (pd->
file.
fp != NULL) request_done = 0;
6798#endif
6799#if MG_ENABLE_HTTP_CGI
6800
6801 if (pd->
cgi.
cgi_nc != NULL) request_done = 0;
6802#endif
6803 if (request_done && io->
len > 0)
goto again;
6804 }
6805 }
6806}
6807
6809 size_t len = 0;
6810 while (len < buf_len && buf[len] != '\n') len++;
6811 return len == buf_len ? 0 : len + 1;
6812}
6813
6814#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6815static void mg_http_multipart_begin(
struct mg_connection *nc,
6820
6821 char boundary_buf[100];
6822 char *boundary = boundary_buf;
6823 int boundary_len;
6824
6826 if (ct == NULL) {
6827
6828 goto exit_mp;
6829 }
6830
6831
6832 if (ct->
len < 9 || strncmp(ct->
p,
"multipart", 9) != 0) {
6833 goto exit_mp;
6834 }
6835
6836 boundary_len =
6838 if (boundary_len == 0) {
6839
6840
6841
6842
6844 DBG((
"invalid request"));
6845 goto exit_mp;
6846 }
6847
6848
6849
6850 if (pd->mp_stream.boundary != NULL) {
6851
6852
6853
6854
6856 } else {
6859 pd->mp_stream.boundary = strdup(boundary);
6860 pd->mp_stream.boundary_len = strlen(boundary);
6861 pd->mp_stream.var_name = pd->mp_stream.file_name = NULL;
6863
6865 if (ep != NULL) {
6867 }
6868
6870
6872 }
6873exit_mp:
6874 if (boundary != boundary_buf)
MG_FREE(boundary);
6875}
6876
6877#define CONTENT_DISPOSITION "Content-Disposition: "
6878
6879static size_t mg_http_multipart_call_handler(
struct mg_connection *
c,
int ev,
6881 size_t data_len) {
6884 memset(&mp, 0, sizeof(mp));
6885
6886 mp.
var_name = pd->mp_stream.var_name;
6890 mp.data.len = data_len;
6891 mp.num_data_consumed = data_len;
6894 pd->mp_stream.data_avail = (mp.num_data_consumed != data_len);
6895 return mp.num_data_consumed;
6896}
6897
6900
6901 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_END, NULL, 0);
6902 MG_FREE((
void *) pd->mp_stream.file_name);
6903 pd->mp_stream.file_name = NULL;
6904 MG_FREE((
void *) pd->mp_stream.var_name);
6905 pd->mp_stream.var_name = NULL;
6906 mg_http_multipart_call_handler(
c, MG_EV_HTTP_MULTIPART_REQUEST_END, NULL, 0);
6907 mg_http_free_proto_data_mp_stream(&pd->mp_stream);
6909
6910 return 1;
6911}
6912
6913static int mg_http_multipart_wait_for_boundary(
struct mg_connection *
c) {
6914 const char *boundary;
6915 struct mbuf *io = &
c->recv_mbuf;
6917
6918 if (pd->mp_stream.boundary == NULL) {
6920 DBG((
"Invalid request: boundary not initialized"));
6921 return 0;
6922 }
6923
6924 if ((
int) io->
len < pd->mp_stream.boundary_len + 2) {
6925 return 0;
6926 }
6927
6929 if (boundary != NULL) {
6930 const char *boundary_end = (boundary + pd->mp_stream.boundary_len);
6931 if (io->
len - (boundary_end - io->
buf) < 4) {
6932 return 0;
6933 }
6934 if (strncmp(boundary_end, "--\r\n", 4) == 0) {
6937 } else {
6939 }
6940 } else {
6941 return 0;
6942 }
6943
6944 return 1;
6945}
6946
6947static void mg_http_parse_header_internal(
struct mg_str *hdr,
6949 struct altbuf *ab);
6950
6951static int mg_http_multipart_process_boundary(
struct mg_connection *
c) {
6952 int data_size;
6953 const char *boundary, *block_begin;
6954 struct mbuf *io = &
c->recv_mbuf;
6956 struct altbuf ab_file_name, ab_var_name;
6957 int line_len;
6959 block_begin = boundary + pd->mp_stream.boundary_len + 2;
6960 data_size = io->
len - (block_begin - io->
buf);
6961
6962 altbuf_init(&ab_file_name, NULL, 0);
6963 altbuf_init(&ab_var_name, NULL, 0);
6964
6965 while (data_size > 0 &&
6967 if (line_len > (int) sizeof(CONTENT_DISPOSITION) &&
6969 sizeof(CONTENT_DISPOSITION) - 1) == 0) {
6971
6972 header.
p = block_begin +
sizeof(CONTENT_DISPOSITION) - 1;
6973 header.len = line_len - sizeof(CONTENT_DISPOSITION) - 1;
6974
6975 altbuf_reset(&ab_var_name);
6976 mg_http_parse_header_internal(&header, "name", &ab_var_name);
6977
6978 altbuf_reset(&ab_file_name);
6979 mg_http_parse_header_internal(&header, "filename", &ab_file_name);
6980
6981 block_begin += line_len;
6982 data_size -= line_len;
6983
6984 continue;
6985 }
6986
6987 if (line_len == 2 &&
mg_ncasecmp(block_begin,
"\r\n", 2) == 0) {
6989
6990 if (pd->mp_stream.processing_part != 0) {
6991 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_END, NULL, 0);
6992 }
6993
6994
6995 altbuf_append(&ab_file_name, '\0');
6996 altbuf_append(&ab_file_name, '\0');
6997 altbuf_append(&ab_var_name, '\0');
6998 altbuf_append(&ab_var_name, '\0');
6999
7000 MG_FREE((
void *) pd->mp_stream.file_name);
7001 pd->mp_stream.file_name = altbuf_get_buf(&ab_file_name, 1 );
7002 MG_FREE((
void *) pd->mp_stream.var_name);
7003 pd->mp_stream.var_name = altbuf_get_buf(&ab_var_name, 1 );
7004
7005 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_BEGIN, NULL, 0);
7007 pd->mp_stream.processing_part++;
7008 return 1;
7009 }
7010
7011 block_begin += line_len;
7012 }
7013
7015
7016 altbuf_reset(&ab_var_name);
7017 altbuf_reset(&ab_file_name);
7018
7019 return 0;
7020}
7021
7022static int mg_http_multipart_continue_wait_for_chunk(
struct mg_connection *
c) {
7024 struct mbuf *io = &
c->recv_mbuf;
7025
7026 const char *boundary;
7027 if ((
int) io->
len < pd->mp_stream.boundary_len + 6 ) {
7028 return 0;
7029 }
7030
7032 if (boundary == NULL) {
7033 int data_len = (io->
len - (pd->mp_stream.boundary_len + 6));
7034 if (data_len > 0) {
7035 size_t consumed = mg_http_multipart_call_handler(
7036 c, MG_EV_HTTP_PART_DATA, io->
buf, (
size_t) data_len);
7038 }
7039 return 0;
7040 } else if (boundary != NULL) {
7041 size_t data_len = ((size_t)(boundary - io->
buf) - 4);
7042 size_t consumed = mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_DATA,
7045 if (consumed == data_len) {
7048 return 1;
7049 } else {
7050 return 0;
7051 }
7052 } else {
7053 return 0;
7054 }
7055}
7056
7059 while (1) {
7060 switch (pd->mp_stream.state) {
7063 break;
7064 }
7066 if (mg_http_multipart_wait_for_boundary(
c) == 0) {
7067 return;
7068 }
7069 break;
7070 }
7072 if (mg_http_multipart_process_boundary(
c) == 0) {
7073 return;
7074 }
7075 break;
7076 }
7078 if (mg_http_multipart_continue_wait_for_chunk(
c) == 0) {
7079 return;
7080 }
7081 break;
7082 }
7084 if (mg_http_multipart_finalize(
c) == 0) {
7085 return;
7086 }
7087 break;
7088 }
7090 return;
7091 }
7092 }
7093 }
7094}
7095
7096struct file_upload_state {
7097 char *lfn;
7098 size_t num_recd;
7100};
7101
7102#endif
7103
7106}
7107
7108const char *mg_status_message(int status_code) {
7109 switch (status_code) {
7110 case 206:
7111 return "Partial Content";
7112 case 301:
7113 return "Moved";
7114 case 302:
7115 return "Found";
7116 case 400:
7117 return "Bad Request";
7118 case 401:
7119 return "Unauthorized";
7120 case 403:
7121 return "Forbidden";
7122 case 404:
7123 return "Not Found";
7124 case 416:
7125 return "Requested Range Not Satisfiable";
7126 case 418:
7127 return "I'm a teapot";
7128 case 500:
7129 return "Internal Server Error";
7130 case 502:
7131 return "Bad Gateway";
7132 case 503:
7133 return "Service Unavailable";
7134
7135#if MG_ENABLE_EXTRA_ERRORS_DESC
7136 case 100:
7137 return "Continue";
7138 case 101:
7139 return "Switching Protocols";
7140 case 102:
7141 return "Processing";
7142 case 200:
7143 return "OK";
7144 case 201:
7145 return "Created";
7146 case 202:
7147 return "Accepted";
7148 case 203:
7149 return "Non-Authoritative Information";
7150 case 204:
7151 return "No Content";
7152 case 205:
7153 return "Reset Content";
7154 case 207:
7155 return "Multi-Status";
7156 case 208:
7157 return "Already Reported";
7158 case 226:
7159 return "IM Used";
7160 case 300:
7161 return "Multiple Choices";
7162 case 303:
7163 return "See Other";
7164 case 304:
7165 return "Not Modified";
7166 case 305:
7167 return "Use Proxy";
7168 case 306:
7169 return "Switch Proxy";
7170 case 307:
7171 return "Temporary Redirect";
7172 case 308:
7173 return "Permanent Redirect";
7174 case 402:
7175 return "Payment Required";
7176 case 405:
7177 return "Method Not Allowed";
7178 case 406:
7179 return "Not Acceptable";
7180 case 407:
7181 return "Proxy Authentication Required";
7182 case 408:
7183 return "Request Timeout";
7184 case 409:
7185 return "Conflict";
7186 case 410:
7187 return "Gone";
7188 case 411:
7189 return "Length Required";
7190 case 412:
7191 return "Precondition Failed";
7192 case 413:
7193 return "Payload Too Large";
7194 case 414:
7195 return "URI Too Long";
7196 case 415:
7197 return "Unsupported Media Type";
7198 case 417:
7199 return "Expectation Failed";
7200 case 422:
7201 return "Unprocessable Entity";
7202 case 423:
7203 return "Locked";
7204 case 424:
7205 return "Failed Dependency";
7206 case 426:
7207 return "Upgrade Required";
7208 case 428:
7209 return "Precondition Required";
7210 case 429:
7211 return "Too Many Requests";
7212 case 431:
7213 return "Request Header Fields Too Large";
7214 case 451:
7215 return "Unavailable For Legal Reasons";
7216 case 501:
7217 return "Not Implemented";
7218 case 504:
7219 return "Gateway Timeout";
7220 case 505:
7221 return "HTTP Version Not Supported";
7222 case 506:
7223 return "Variant Also Negotiates";
7224 case 507:
7225 return "Insufficient Storage";
7226 case 508:
7227 return "Loop Detected";
7228 case 510:
7229 return "Not Extended";
7230 case 511:
7231 return "Network Authentication Required";
7232#endif
7233
7234 default:
7235 return "OK";
7236 }
7237}
7238
7239void mg_send_response_line_s(
struct mg_connection *nc,
int status_code,
7240 const struct mg_str extra_headers) {
7241 mg_printf(nc,
"HTTP/1.1 %d %s\r\n", status_code,
7242 mg_status_message(status_code));
7243#ifndef MG_HIDE_SERVER_INFO
7244 mg_printf(nc,
"Server: %s\r\n", mg_version_header);
7245#endif
7246 if (extra_headers.
len > 0) {
7247 mg_printf(nc,
"%.*s\r\n", (
int) extra_headers.
len, extra_headers.
p);
7248 }
7249}
7250
7252 const char *extra_headers) {
7253 mg_send_response_line_s(nc, status_code,
mg_mk_str(extra_headers));
7254}
7255
7257 const struct mg_str location,
7258 const struct mg_str extra_headers) {
7259 char bbody[100], *pbody = bbody;
7261 "<p>Moved <a href='%.*s'>here</a>.\r\n",
7262 (
int) location.
len, location.
p);
7263 char bhead[150], *phead = bhead;
7265 "Location: %.*s\r\n"
7266 "Content-Type: text/html\r\n"
7267 "Content-Length: %d\r\n"
7268 "Cache-Control: no-cache\r\n"
7269 "%.*s%s",
7270 (
int) location.
len, location.
p,
bl, (
int) extra_headers.
len,
7271 extra_headers.
p, (extra_headers.
len > 0 ?
"\r\n" :
""));
7273 if (phead != bhead)
MG_FREE(phead);
7275 if (pbody != bbody)
MG_FREE(pbody);
7276}
7277
7279 int64_t content_length, const char *extra_headers) {
7281 if (content_length < 0) {
7282 mg_printf(
c,
"%s",
"Transfer-Encoding: chunked\r\n");
7283 } else {
7285 }
7287}
7288
7290 const char *reason) {
7291 if (!reason) reason = mg_status_message(code);
7294 "Content-Type: text/plain\r\nConnection: close");
7295 mg_send(nc, reason, strlen(reason));
7297}
7298
7299#if MG_ENABLE_FILESYSTEM
7301 const cs_stat_t *st) {
7302 snprintf(buf, buf_len,
"\"%lx.%" INT64_FMT "\"", (
unsigned long) st->st_mtime,
7303 (int64_t) st->st_size);
7304}
7305
7306#ifndef WINCE
7308 strftime(buf, buf_len,
"%a, %d %b %Y %H:%M:%S GMT",
gmtime(t));
7309}
7310#else
7311
7313#endif
7314
7316 int64_t *b) {
7317
7318
7319
7320
7321 int result;
7323 if (p == NULL) return 0;
7324 memcpy(p, header->
p, header->
len);
7325 p[header->
len] =
'\0';
7328 return result;
7329}
7330
7333 const struct mg_str extra_headers) {
7335 cs_stat_t st;
7339 switch (err) {
7340 case EACCES:
7341 code = 403;
7342 break;
7343 case ENOENT:
7344 code = 404;
7345 break;
7346 default:
7347 code = 500;
7348 };
7350 } else {
7351 char etag[50], current_time[50], last_modified[50], range[70];
7352 time_t t = (time_t)
mg_time();
7353 int64_t r1 = 0, r2 = 0, cl = st.st_size;
7355 int n, status_code = 200;
7356
7357
7358 range[0] = '\0';
7359 if (range_hdr != NULL &&
7361 r2 >= 0) {
7362
7364 r2 = cl - 1;
7365 }
7366 if (r1 > r2 || r2 >= cl) {
7367 status_code = 416;
7368 cl = 0;
7369 snprintf(range, sizeof(range),
7370 "Content-Range: bytes */%" INT64_FMT "\r\n",
7371 (int64_t) st.st_size);
7372 } else {
7373 status_code = 206;
7374 cl = r2 - r1 + 1;
7375 snprintf(range,
sizeof(range),
"Content-Range: bytes %" INT64_FMT
7377 r1, r1 + cl - 1, (int64_t) st.st_size);
7378#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \
7379 _XOPEN_SOURCE >= 600
7380 fseeko(pd->
file.
fp, r1, SEEK_SET);
7381#else
7382 fseek(pd->
file.
fp, (
long) r1, SEEK_SET);
7383#endif
7384 }
7385 }
7386
7387#if !MG_DISABLE_HTTP_KEEP_ALIVE
7388 {
7390 if (conn_hdr != NULL) {
7392 } else {
7394 }
7395 }
7396#endif
7397
7401
7402
7403
7404
7405
7406
7407
7408 mg_send_response_line_s(nc, status_code, extra_headers);
7410 "Date: %s\r\n"
7411 "Last-Modified: %s\r\n"
7412 "Accept-Ranges: bytes\r\n"
7413 "Content-Type: %.*s\r\n"
7414 "Connection: %s\r\n"
7415 "Content-Length: %" SIZE_T_FMT
7416 "\r\n"
7417 "%sEtag: %s\r\n\r\n",
7419 (pd->
file.keepalive ?
"keep-alive" :
"close"), (size_t) cl, range,
7420 etag);
7421
7425 }
7426}
7427
7428static void mg_http_serve_file2(
struct mg_connection *nc,
const char *path,
7431#if MG_ENABLE_HTTP_SSI
7434 return;
7435 }
7436#endif
7437 mg_http_serve_file(nc, hm, path,
mg_get_mime_type(path,
"text/plain", opts),
7439}
7440
7441#endif
7442
7443int mg_url_decode(
const char *src,
int src_len,
char *dst,
int dst_len,
7444 int is_form_url_encoded) {
7446#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
7447
7448 for (
i =
j = 0;
i < src_len &&
j < dst_len - 1;
i++,
j++) {
7449 if (src[
i] ==
'%') {
7450 if (
i < src_len - 2 && isxdigit(*(
const unsigned char *) (src +
i + 1)) &&
7451 isxdigit(*(
const unsigned char *) (src +
i + 2))) {
7452 a = tolower(*(
const unsigned char *) (src +
i + 1));
7453 b = tolower(*(
const unsigned char *) (src +
i + 2));
7456 } else {
7457 return -1;
7458 }
7459 }
else if (is_form_url_encoded && src[
i] ==
'+') {
7461 } else {
7463 }
7464 }
7465
7467
7468 return i >= src_len ?
j : -1;
7469}
7470
7472 size_t dst_len) {
7473 const char *
p, *
e, *s;
7474 size_t name_len;
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485 if (dst == NULL || dst_len == 0) {
7487 }
else if (buf->
p == NULL ||
name == NULL || buf->
len == 0) {
7489 dst[0] = '\0';
7490 } else {
7491 name_len = strlen(
name);
7492 e = buf->
p + buf->
len;
7494 dst[0] = '\0';
7495
7496 for (
p = buf->
p;
p + name_len <
e;
p++) {
7497 if ((
p == buf->
p ||
p[-1] ==
'&') &&
p[name_len] ==
'=' &&
7500 s = (
const char *) memchr(
p,
'&', (
size_t)(
e -
p));
7501 if (s == NULL) {
7503 }
7505
7508 }
7509 break;
7510 }
7511 }
7512 }
7513
7515}
7516
7518 char chunk_size[50];
7520
7521 n = snprintf(chunk_size,
sizeof(chunk_size),
"%lX\r\n", (
unsigned long)
len);
7525}
7526
7530 va_list ap;
7531
7532 va_start(ap, fmt);
7534 va_end(ap);
7535
7538 }
7539
7540
7541 if (buf != mem && buf != NULL) {
7543 }
7544
7545}
7546
7550 va_list ap;
7551
7552 va_start(ap, fmt);
7554 va_end(ap);
7555
7557 for (
i =
j = 0;
i <
len;
i++) {
7558 if (buf[
i] ==
'<' || buf[
i] ==
'>') {
7560 mg_send(nc, buf[
i] ==
'<' ?
"<" :
">", 4);
7562 }
7563 }
7565 }
7566
7567
7568 if (buf != mem && buf != NULL) {
7570 }
7571
7572}
7573
7574static void mg_http_parse_header_internal(
struct mg_str *hdr,
7576 struct altbuf *ab) {
7577 int ch =
' ', ch1 =
',', ch2 =
';',
n = strlen(
var_name);
7578 const char *
p, *
end = hdr ? hdr->
p + hdr->
len : NULL, *s = NULL;
7579
7580
7581 for (s = hdr->
p; s != NULL && s +
n <
end; s++) {
7582 if ((s == hdr->
p || s[-1] == ch || s[-1] == ch1 || s[-1] ==
';') &&
7584 break;
7585 }
7586
7587 if (s != NULL && &s[
n + 1] <
end) {
7589 if (*s == '"' || *s == '\'') {
7590 ch = ch1 = ch2 = *s++;
7591 }
7593 while (
p <
end &&
p[0] != ch &&
p[0] != ch1 &&
p[0] != ch2) {
7594 if (ch !=
' ' &&
p[0] ==
'\\' &&
p[1] == ch)
p++;
7595 altbuf_append(ab, *
p++);
7596 }
7597
7598 if (ch !=
' ' && *
p != ch) {
7599 altbuf_reset(ab);
7600 }
7601 }
7602
7603
7604 if (ab->len > 0) {
7605 altbuf_append(ab, '\0');
7606 }
7607}
7608
7610 size_t buf_size) {
7611 struct altbuf ab;
7612 altbuf_init(&ab, *buf, buf_size);
7613 if (hdr == NULL) return 0;
7614 if (*buf != NULL && buf_size > 0) *buf[0] = '\0';
7615
7616 mg_http_parse_header_internal(hdr,
var_name, &ab);
7617
7618
7619
7620
7621
7622 *buf = altbuf_get_buf(&ab, 1 );
7623 return ab.len > 0 ? ab.len - 1 : 0;
7624}
7625
7627 size_t buf_size) {
7628 char *buf2 = buf;
7629
7631
7632 if (buf2 != buf) {
7633
7635 return 0;
7636 }
7637
7638 return len;
7639}
7640
7642 char *pass, size_t pass_len) {
7644 if (hdr == NULL) return -1;
7646}
7647
7649 char *pass, size_t pass_len) {
7650 char *buf = NULL;
7651 char fmt[64];
7652 int res = 0;
7653
7655
7658
7659
7660 snprintf(fmt, sizeof(fmt), "%%%" SIZE_T_FMT "[^:]:%%%" SIZE_T_FMT "[^\n]",
7661 user_len - 1, pass_len - 1);
7662 if (sscanf(buf, fmt, user, pass) == 0) {
7663 res = -1;
7664 }
7665
7667 return res;
7668}
7669
7670#if MG_ENABLE_FILESYSTEM
7673 int exclude_specials) {
7676
7677
7678 const char *pdir = strrchr(path, DIRSEP);
7679 if (pdir != NULL) {
7680 path = pdir + 1;
7681 }
7682
7683 return (exclude_specials && (!strcmp(path, ".") || !strcmp(path, ".."))) ||
7684 (p1 != NULL &&
mg_match_prefix(p1, strlen(p1), path) == strlen(p1)) ||
7686}
7687
7688#if !MG_DISABLE_HTTP_DIGEST_AUTH
7689
7690#ifndef MG_EXT_MD5
7692 const size_t *msg_lens, uint8_t *digest) {
7696 for (
i = 0;
i < num_msgs;
i++) {
7698 }
7700}
7701#else
7702extern void mg_hash_md5_v(
size_t num_msgs,
const uint8_t *msgs[],
7703 const size_t *msg_lens, uint8_t *digest);
7704#endif
7705
7706void cs_md5(
char buf[33], ...) {
7707 unsigned char hash[16];
7708 const uint8_t *msgs[20], *
p;
7709 size_t msg_lens[20];
7710 size_t num_msgs = 0;
7711 va_list ap;
7712
7713 va_start(ap, buf);
7714 while ((
p = va_arg(ap,
const unsigned char *) ) != NULL) {
7716 msg_lens[num_msgs] = va_arg(ap, size_t);
7717 num_msgs++;
7718 }
7719 va_end(ap);
7720
7723}
7724
7725static void mg_mkmd5resp(
const char *method,
size_t method_len,
const char *uri,
7726 size_t uri_len, const char *ha1, size_t ha1_len,
7727 const char *nonce, size_t nonce_len, const char *nc,
7728 size_t nc_len, const char *cnonce, size_t cnonce_len,
7729 const char *qop, size_t qop_len, char *resp) {
7730 static const char colon[] = ":";
7731 static const size_t one = 1;
7732 char ha2[33];
7733 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
7734 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
7735 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
7736 colon, one, ha2, sizeof(ha2) - 1, NULL);
7737}
7738
7740 const char *method, const char *uri,
7741 const char *auth_domain, const char *user,
7742 const char *passwd, const char *nonce) {
7743 static const char colon[] = ":", qop[] = "auth";
7744 static const size_t one = 1;
7745 char ha1[33], resp[33], cnonce[40];
7746
7747 snprintf(cnonce,
sizeof(cnonce),
"%lx", (
unsigned long)
mg_time());
7748 cs_md5(ha1, user, (
size_t) strlen(user), colon, one, auth_domain,
7749 (size_t) strlen(auth_domain), colon, one, passwd,
7750 (size_t) strlen(passwd), NULL);
7751 mg_mkmd5resp(method, strlen(method), uri, strlen(uri), ha1,
sizeof(ha1) - 1,
7752 nonce, strlen(nonce), "1", one, cnonce, strlen(cnonce), qop,
7753 sizeof(qop) - 1, resp);
7754 return snprintf(buf, buf_len,
7755 "Authorization: Digest username=\"%s\","
7756 "realm=\"%s\",uri=\"%s\",qop=%s,nc=1,cnonce=%s,"
7757 "nonce=%s,response=%s\r\n",
7758 user, auth_domain, uri, qop, cnonce, nonce, resp);
7759}
7760
7761
7762
7763
7764
7765
7766
7768 unsigned long now = (
unsigned long)
mg_time();
7769 unsigned long val = (unsigned long) strtoul(nonce, NULL, 16);
7770 return (now >= val) && (now - val < 60 * 60);
7771}
7772
7775 int ret = 0;
7777 char username_buf[50], cnonce_buf[64], response_buf[40], uri_buf[200],
7778 qop_buf[20], nc_buf[20], nonce_buf[16];
7779
7780 char *username = username_buf, *cnonce = cnonce_buf, *
response = response_buf,
7781 *uri = uri_buf, *qop = qop_buf, *nc = nc_buf, *nonce = nonce_buf;
7782
7783
7784 if (hm == NULL ||
fp == NULL ||
7787 0 ||
7790 0 ||
7796 ret = 0;
7797 goto clean;
7798 }
7799
7800
7801
7810
7811clean:
7812 if (username != username_buf)
MG_FREE(username);
7813 if (cnonce != cnonce_buf)
MG_FREE(cnonce);
7815 if (uri != uri_buf)
MG_FREE(uri);
7816 if (qop != qop_buf)
MG_FREE(qop);
7817 if (nc != nc_buf)
MG_FREE(nc);
7818 if (nonce != nonce_buf)
MG_FREE(nonce);
7819
7820 return ret;
7821}
7822
7827 struct mg_str auth_domain, FILE *
fp) {
7828 char buf[128], f_user[sizeof(buf)], f_ha1[sizeof(buf)], f_domain[sizeof(buf)];
7829 char exp_resp[33];
7830
7831
7832
7833
7834
7835
7836 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
7837 if (sscanf(buf, "%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3 &&
7838 mg_vcmp(&username, f_user) == 0 &&
7839 mg_vcmp(&auth_domain, f_domain) == 0) {
7840
7842 nonce.
p, nonce.
len, nc.
p, nc.
len, cnonce.
p, cnonce.
len,
7843 qop.
p, qop.
len, exp_resp);
7847 }
7848 }
7849
7850
7851 return 0;
7852}
7853
7855 const char *domain, const char *passwords_file,
7856 int flags) {
7860 int authorized = 1;
7861
7862 if (domain != NULL && passwords_file != NULL) {
7866 snprintf(buf,
sizeof(buf),
"%.*s%c%s", (
int) path.
len, path.
p, DIRSEP,
7867 passwords_file);
7869 } else {
7870 p = strrchr(path.
p, DIRSEP);
7871 if (
p == NULL)
p = path.
p;
7872 snprintf(buf,
sizeof(buf),
"%.*s%c%s", (
int) (
p - path.
p), path.
p, DIRSEP,
7873 passwords_file);
7875 }
7876
7881 authorized = 0;
7882 }
7883 }
7884
7886 passwords_file ? passwords_file : "", flags, authorized));
7887 return authorized;
7888}
7889#else
7891 const char *domain, const char *passwords_file,
7892 int flags) {
7893 (void) hm;
7894 (void) path;
7895 (void) domain;
7896 (void) passwords_file;
7897 (void) flags;
7898 return 1;
7899}
7900#endif
7901
7902#if MG_ENABLE_DIRECTORY_LISTING
7903static void mg_escape(
const char *src,
char *dst,
size_t dst_len) {
7905 while (*src !=
'\0' &&
n + 5 < dst_len) {
7906 unsigned char ch = *(unsigned char *) src++;
7907 if (ch == '<') {
7908 n += snprintf(dst +
n, dst_len -
n,
"%s",
"<");
7909 } else {
7911 }
7912 }
7914}
7915
7917 cs_stat_t *stp) {
7919 int64_t fsize = stp->st_size;
7920 int is_dir = S_ISDIR(stp->st_mode);
7921 const char *slash = is_dir ? "/" : "";
7923
7924 if (is_dir) {
7925 snprintf(size, sizeof(size), "%s", "[DIRECTORY]");
7926 } else {
7927
7928
7929
7930
7931 if (fsize < 1024) {
7932 snprintf(size, sizeof(size), "%d", (int) fsize);
7933 } else if (fsize < 0x100000) {
7934 snprintf(size, sizeof(size), "%.1fk", (double) fsize / 1024.0);
7935 } else if (fsize < 0x40000000) {
7936 snprintf(size, sizeof(size), "%.1fM", (double) fsize / 1048576);
7937 } else {
7938 snprintf(size, sizeof(size), "%.1fG", (double) fsize / 1073741824);
7939 }
7940 }
7941 strftime(mod,
sizeof(mod),
"%d-%b-%Y %H:%M",
localtime(&stp->st_mtime));
7945 "<tr><td><a href=\"%s%s\">%s%s</a></td>"
7946 "<td>%s</td><td name=%" INT64_FMT ">%s</td></tr>\n",
7947 href.p, slash, path, slash, mod, is_dir ? -1 : fsize,
7948 size);
7949 free((void *) href.p);
7950}
7951
7955 cs_stat_t *)) {
7957 cs_stat_t st;
7958 struct dirent *dp;
7960
7962 if ((dirp = (opendir(dir))) != NULL) {
7963 while ((dp = readdir(dirp)) != NULL) {
7964
7966 continue;
7967 }
7968 snprintf(path, sizeof(path), "%s/%s", dir, dp->d_name);
7969 if (
mg_stat(path, &st) == 0) {
7970 func(nc, (const char *) dp->d_name, &st);
7971 }
7972 }
7973 closedir(dirp);
7974 } else {
7976 }
7977}
7978
7982 static const char *sort_js_code =
7983 "<script>function srt(tb, sc, so, d) {"
7984 "var tr = Array.prototype.slice.call(tb.rows, 0),"
7985 "tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
7986 "n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
7987 "t1 = a.cells[2].getAttribute('name'), "
7988 "t2 = b.cells[2].getAttribute('name'); "
7989 "return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
7990 "n1 ? parseInt(n2) - parseInt(n1) : "
7991 "c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
7992 static const char *sort_js_code2 =
7993 "for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
7994 "if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
7995 "};"
7996 "window.onload = function() {"
7997 "var tb = document.getElementById('tb');"
7998 "var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
7999 "var sc = m[1], so = m[2]; document.onclick = function(ev) { "
8000 "var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
8001 "sc = c; ev.preventDefault();}};"
8002 "srt(tb, sc, so, true);"
8003 "}"
8004 "</script>";
8005
8007 mg_printf(nc,
"%s: %s\r\n%s: %s\r\n\r\n",
"Transfer-Encoding",
"chunked",
8008 "Content-Type", "text/html; charset=utf-8");
8009
8011 nc,
8012 "<html><head><title>Index of %.*s</title>%s%s"
8013 "<style>th,td {text-align: left; padding-right: 1em; "
8014 "font-family: monospace; }</style></head>\n"
8015 "<body><h1>Index of %.*s</h1>\n<table cellpadding=0><thead>"
8016 "<tr><th><a href=# rel=0>Name</a></th><th>"
8017 "<a href=# rel=1>Modified</a</th>"
8018 "<th><a href=# rel=2>Size</a></th></tr>"
8019 "<tr><td colspan=3><hr></td></tr>\n"
8020 "</thead>\n"
8021 "<tbody id=tb>",
8022 (
int) hm->
uri.
len, hm->
uri.
p, sort_js_code, sort_js_code2,
8026 "</tbody><tr><td colspan=3><hr></td></tr>\n"
8027 "</table>\n"
8028 "<address>%s</address>\n"
8029 "</body></html>",
8030 mg_version_header);
8032
8034}
8035#endif
8036
8037
8038
8039
8040
8041
8042
8043
8045 char **index_file, cs_stat_t *stp) {
8047 size_t path_len = strlen(path);
8048 int found = 0;
8049 *index_file = NULL;
8050
8051
8052
8054 cs_stat_t st;
8055 size_t len = path_len + 1 +
vec.
len + 1;
8057 if (*index_file == NULL) break;
8058 snprintf(*index_file,
len,
"%s%c%.*s", path, DIRSEP, (
int)
vec.
len,
vec.p);
8059
8060
8061 if (
mg_stat(*index_file, &st) == 0 && S_ISREG(st.st_mode)) {
8062
8063 *stp = st;
8064 found = 1;
8065 break;
8066 }
8067 }
8068 if (!found) {
8070 *index_file = NULL;
8071 }
8072 LOG(
LL_DEBUG, (
"[%s] [%s]", path, (*index_file ? *index_file :
"")));
8073}
8074
8075#if MG_ENABLE_HTTP_URL_REWRITES
8081 char local_port[20] = {'%'};
8082
8085
8087 if (
mg_vcmp(&a, local_port) == 0) {
8089 mg_printf(
c,
"Content-Length: 0\r\nLocation: %.*s%.*s\r\n\r\n",
8090 (
int) b.len, b.p, (
int) (hm->
proto.
p - hm->
uri.
p - 1),
8092 return 1;
8093 }
8094 }
8095
8096 return 0;
8097}
8098
8099static uint64_t ContentLength(const std::string& msg)
8100{
8101 const char* CRLFCRLF = "\r\n\r\n";
8102 size_t pos = msg.find(CRLFCRLF);
8103 if (pos == std::string::npos) {
8104 return 0;
8105 }
8106
8107 return msg.length() - pos - 4;
8108}
8109
8110static void SetContentLength(std::string& msg, uint64_t
len)
8111{
8112 const char* CRLF = "\r\n";
8113 const char* CL = "Content-Length: ";
8114 size_t pos = msg.find(CL);
8115 if (pos == std::string::npos) {
8116 return;
8117 }
8118 pos += strlen(CL);
8119 size_t pos2 = msg.find(CRLF, pos);
8120 if (pos2 == std::string::npos) {
8121 return;
8122 }
8123 char buf[256];
8124 sprintf(buf,
"%llu", (
long long unsigned)
len);
8125 msg.replace(pos, pos2-pos, buf);
8126
8127}
8128
8129bool Rewrite(std::string&
message,
const char* re,
const char* rs)
8130{
8131 bool changed = false;
8132 size_t pos = 0;
8133 size_t len = strlen(re);
8134 while (1) {
8136 if (pos == std::string::npos) {
8137 break;
8138 }
8140 changed = true;
8141 }
8142 return changed;
8143}
8144
8145static void mg_reverse_proxy_handler(
struct mg_connection *nc,
int ev,
8146 void *ev_data
MG_UD_ARG(
void *user_data)) {
8149
8150 if (pd == NULL || pd->reverse_proxy_data.linked_conn == NULL) {
8151 DBG((
"%p: upstream closed", nc));
8152 return;
8153 }
8154
8155
8156
8157
8158
8159 switch (ev) {
8161 if (*(int *) ev_data != 0) {
8163 }
8164 break;
8165
8167
8168
8169 break;
8170 }
8172
8173
8174
8175
8176
8178 xstr.
p =
"Transfer-Encoding: chunked";
8179 xstr.
len = strlen(xstr.
p);
8181 if (s) {
8182 *(char*)s = 'X';
8183 }
8184
8185 if (0) {
8187
8188
8189
8190
8191
8192
8193
8194
8195 bool changed = false;
8196 std::string
message = message_in;
8197 changed |= Rewrite(
message,
"href=\"/",
"href=\"");
8198 changed |= Rewrite(
message,
"src=\"/",
"src=\"");
8199
8200 changed |= Rewrite(
message,
"post(\"/api/",
"post(\"api/");
8201 if (changed) {
8202
8204
8206 } else {
8208 }
8209 } else {
8211 }
8214 break;
8215 }
8218
8220 mg_send(pd->reverse_proxy_data.linked_conn, io->
buf, io->
len);
8221 }
8223 break;
8224 }
8225 }
8226
8227#if MG_ENABLE_CALLBACK_USERDATA
8228 (void) user_data;
8229#endif
8230}
8231
8234 struct mg_str upstream) {
8236 char burl[256], *purl = burl;
8238 const char *error;
8241 memset(&opts, 0, sizeof(opts));
8242 opts.error_string = &error;
8243
8244 mg_asprintf(&purl,
sizeof(burl),
"%.*s%.*s%s%.*s", (
int) upstream.
len, upstream.
p,
8246
8247
8248
8250 opts, "http", NULL, "https", NULL, purl, &path,
8251 &user_info, &host);
8253 hm->
uri.
p, purl, (
int) mount.
len, mount.
p));
8254
8255 if (be == NULL) {
8256 LOG(
LL_ERROR, (
"Error connecting to %s: %s", purl, error));
8258 goto cleanup;
8259 }
8260
8261 mg_http_create_proto_data(be);
8262
8263
8266
8267
8269 (
int) path.
len, path.
p);
8270
8271 mg_printf(be,
"Host: %.*s\r\n", (
int) host.len, host.p);
8275
8276
8278
8279
8280
8281
8285 continue;
8286 }
8287
8290 continue;
8291 }
8292
8294 }
8295
8298
8299cleanup:
8300 if (purl != burl)
MG_FREE(purl);
8301}
8302
8303static int mg_http_handle_forwarding(
struct mg_connection *nc,
8309
8313 mg_http_reverse_proxy(nc, hm, a, b);
8314 return 1;
8315 }
8316 }
8317 }
8318
8319 return 0;
8320}
8321#endif
8322
8323#if 0
8326 char **local_path,
8327 struct mg_str *remainder) {
8328 int ok = 1;
8330 struct mg_str root = {NULL, 0};
8331 const char *file_uri_start = cp;
8332 *local_path = NULL;
8333 remainder->
p = NULL;
8335
8336 {
8337
8338#if MG_ENABLE_HTTP_URL_REWRITES
8340#else
8341 const char *rewrites = "";
8342#endif
8345
8347 if (a.len > 1 && a.p[0] == '@') {
8348
8349 if (hh != NULL && hh->
len == a.len - 1 &&
8351 root = b;
8352 break;
8353 }
8354 } else {
8355
8357 if (match_len > 0) {
8358 file_uri_start = hm->
uri.
p + match_len;
8359 if (*file_uri_start == '/' || file_uri_start == cp_end) {
8360
8361 } else if (*(file_uri_start - 1) == '/') {
8362
8363 file_uri_start--;
8364 } else {
8365
8366 continue;
8367 }
8368 root = b;
8369 break;
8370 }
8371 }
8372 }
8373
8374 if (root.
p == NULL) {
8375#if MG_ENABLE_HTTP_WEBDAV
8379 } else
8380#endif
8381 {
8384 }
8385 }
8386 assert(root.
p != NULL && root.
len > 0);
8387 }
8388
8389 {
8390 const char *u = file_uri_start + 1;
8392 char *lp_end = lp + root.
len + hm->
uri.
len + 1;
8394 int exists = 1;
8395 if (lp == NULL) {
8396 ok = 0;
8397 goto out;
8398 }
8399 memcpy(
p, root.
p, root.
len);
8401 if (*(
p - 1) == DIRSEP)
p--;
8404
8405
8406 while (u <= cp_end) {
8407 const char *next = u;
8409 if (exists) {
8410 cs_stat_t st;
8411 exists = (
mg_stat(lp, &st) == 0);
8412 if (exists && S_ISREG(st.st_mode)) {
8413
8414
8415 if (*(u - 1) == '/') u--;
8416 break;
8417 }
8418 }
8419 if (u >= cp_end) break;
8421 if (component.len > 0) {
8423 memmove(
p + 1, component.p, component.len);
8426 ok = 0;
8427 break;
8428 }
8429 component.p =
p + 1;
8430 component.len =
len;
8431 if (
mg_vcmp(&component,
".") == 0) {
8432
8433 }
else if (
mg_vcmp(&component,
"..") == 0) {
8434 while (
p > ps && *
p != DIRSEP)
p--;
8436 } else {
8438#ifdef _WIN32
8439
8441 if (to_wchar(component.p, buf,
MG_MAX_PATH) == 0) {
8442 DBG((
"[%.*s] smells funny", (
int) component.len, component.p));
8443 ok = 0;
8444 break;
8445 }
8446#endif
8448
8449 for (
i = 0;
i < component.len;
i++,
p++) {
8450 if (*
p ==
'\0' || *
p == DIRSEP
8451#ifdef _WIN32
8452
8453 ||
8455#endif
8456 ) {
8457 ok = 0;
8458 break;
8459 }
8460 }
8461 }
8462 }
8463 u = next;
8464 }
8465 if (ok) {
8466 *local_path = lp;
8467 if (u > cp_end) u = cp_end;
8469 remainder->
len = cp_end - u;
8470 } else {
8472 }
8473 }
8474
8475out:
8477 (
"'%.*s' -> '%s' + '%.*s'", (
int) hm->
uri.
len, hm->
uri.
p,
8478 *local_path ? *local_path :
"", (int) remainder->
len, remainder->
p));
8479 return ok;
8480}
8481#endif
8482
8484 static const char *
month_names[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
8485 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
8487
8490
8491 return -1;
8492}
8493
8495 return year / 4 - year / 100 + year / 400;
8496}
8497
8498
8500 static const unsigned short days_before_month[] = {
8501 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
8502 char month_str[32];
8503 int second, minute, hour, day, month, year, leap_days, days;
8504 time_t result = (time_t) 0;
8505
8506 if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d", &day, month_str, &year, &hour,
8507 &minute, &second) == 6) ||
8508 (sscanf(datetime, "%d %3s %d %d:%d:%d", &day, month_str, &year, &hour,
8509 &minute, &second) == 6) ||
8510 (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", &day, month_str, &year,
8511 &hour, &minute, &second) == 6) ||
8512 (sscanf(datetime, "%d-%3s-%d %d:%d:%d", &day, month_str, &year, &hour,
8513 &minute, &second) == 6)) &&
8516 year -= 1970;
8517 days = year * 365 + days_before_month[month] + (day - 1) + leap_days;
8518 result = days * 24 * 3600 + hour * 3600 + minute * 60 + second;
8519 }
8520
8521 return result;
8522}
8523
8527 char etag[64];
8532 } else {
8533 return 0;
8534 }
8535}
8536
8538 const char *domain) {
8540 "HTTP/1.1 401 Unauthorized\r\n"
8541 "WWW-Authenticate: Digest qop=\"auth\", "
8542 "realm=\"%s\", nonce=\"%lx\"\r\n"
8543 "Content-Length: 0\r\n\r\n",
8544 domain, (
unsigned long)
mg_time());
8545}
8546
8551 "Allow: GET, POST, HEAD, CONNECT, OPTIONS"
8553 ", MKCOL, PUT, DELETE, PROPFIND, MOVE\r\nDAV: 1,2"
8554#endif
8555 "\r\n\r\n");
8557}
8558
8561}
8562
8564 const struct mg_str *path_info,
8567 int exists, is_directory, is_cgi;
8568#if MG_ENABLE_HTTP_WEBDAV
8570#else
8571 int is_dav = 0;
8572#endif
8573 char *index_file = NULL;
8574 cs_stat_t st;
8575
8576 exists = (
mg_stat(path, &st) == 0);
8577 is_directory = exists && S_ISDIR(st.st_mode);
8578
8579 if (is_directory)
8581
8582 is_cgi =
8584 index_file ? index_file : path) > 0);
8585
8587 ("%p %.*s [%s] exists=%d is_dir=%d is_dav=%d is_cgi=%d index=%s", nc,
8589 is_cgi, index_file ? index_file : ""));
8590
8591 if (is_directory && hm->
uri.
p[hm->
uri.
len - 1] !=
'/' && !is_dav) {
8593 "HTTP/1.1 301 Moved\r\nLocation: %.*s/\r\n"
8594 "Content-Length: 0\r\n\r\n",
8597 return;
8598 }
8599
8600
8601 if (path_info->
len > 0 && !is_cgi) {
8604 return;
8605 }
8606
8616 opts->per_directory_auth_file,
8620 } else if (is_cgi) {
8621#if MG_ENABLE_HTTP_CGI
8622 mg_handle_cgi(nc, index_file ? index_file : path, path_info, hm, opts);
8623#else
8625#endif
8626 } else if ((!exists ||
8630#if MG_ENABLE_HTTP_WEBDAV
8633#if !MG_DISABLE_DAV_AUTH
8634 } else if (is_dav &&
8643#endif
8652#if MG_ENABLE_FAKE_DAVLOCK
8654 mg_handle_lock(nc, path);
8655#endif
8656#endif
8659 } else if (is_directory && index_file == NULL) {
8660#if MG_ENABLE_DIRECTORY_LISTING
8663 } else {
8665 }
8666#else
8668#endif
8671 } else {
8672 mg_http_serve_file2(nc, index_file ? index_file : path, hm, opts);
8673 }
8675}
8676
8677#if 0
8680 char *path = NULL;
8681 struct mg_str *hdr, path_info;
8682 uint32_t remote_ip = ntohl(*(uint32_t *) &nc->
sa.
sin.sin_addr);
8683
8685
8688 return;
8689 }
8690
8691#if MG_ENABLE_HTTP_URL_REWRITES
8692 if (mg_http_handle_forwarding(nc, hm, &opts)) {
8693 return;
8694 }
8695
8697 return;
8698 }
8699#endif
8700
8703 }
8706 }
8709 }
8712 }
8715 }
8717 opts.
index_files =
"index.html,index.htm,index.shtml,index.cgi,index.php";
8718 }
8719
8722 return;
8723 }
8726 return;
8727 }
8729
8731 path = NULL;
8732
8733
8736 mg_vcmp(hdr,
"keep-alive") != 0)) {
8737#if 0
8739#endif
8740 }
8741}
8742#endif
8743
8744#if MG_ENABLE_HTTP_STREAMING_MULTIPART
8745void mg_file_upload_handler(
struct mg_connection *nc,
int ev,
void *ev_data,
8746 mg_fu_fname_fn local_name_fn
8748 switch (ev) {
8749 case MG_EV_HTTP_PART_BEGIN: {
8752 struct file_upload_state *fus;
8755 if (lfn.
p == NULL || lfn.
len == 0) {
8758 "HTTP/1.1 403 Not Allowed\r\n"
8759 "Content-Type: text/plain\r\n"
8760 "Connection: close\r\n\r\n"
8761 "Not allowed to upload %s\r\n",
8764 return;
8765 }
8766 fus = (
struct file_upload_state *)
MG_CALLOC(1,
sizeof(*fus));
8767 if (fus == NULL) {
8769 return;
8770 }
8772 memcpy(fus->lfn, lfn.
p, lfn.
len);
8773 fus->lfn[lfn.
len] =
'\0';
8776 (
"%p Receiving file %s -> %s", nc, mp->
file_name, fus->lfn));
8777 fus->fp =
mg_fopen(fus->lfn,
"wb");
8778 if (fus->fp == NULL) {
8780 "HTTP/1.1 500 Internal Server Error\r\n"
8781 "Content-Type: text/plain\r\n"
8782 "Connection: close\r\n\r\n");
8785
8786
8787
8788 }
8790 break;
8791 }
8792 case MG_EV_HTTP_PART_DATA: {
8795 struct file_upload_state *fus =
8796 (
struct file_upload_state *) mp->
user_data;
8797 if (fus == NULL || fus->fp == NULL) break;
8799 LOG(
LL_ERROR, (
"Failed to write to %s: %d, wrote %d", fus->lfn,
8802#ifdef SPIFFS_ERR_FULL
8804#endif
8805 ) {
8807 "HTTP/1.1 413 Payload Too Large\r\n"
8808 "Content-Type: text/plain\r\n"
8809 "Connection: close\r\n\r\n");
8810 mg_printf(nc,
"Failed to write to %s: no space left; wrote %d\r\n",
8811 fus->lfn, (int) fus->num_recd);
8812 } else {
8814 "HTTP/1.1 500 Internal Server Error\r\n"
8815 "Content-Type: text/plain\r\n"
8816 "Connection: close\r\n\r\n");
8819 }
8820 fclose(fus->fp);
8821 remove(fus->lfn);
8822 fus->fp = NULL;
8823
8824
8825
8826 return;
8827 }
8828 fus->num_recd += mp->
data.
len;
8830 (int) fus->num_recd));
8831 break;
8832 }
8833 case MG_EV_HTTP_PART_END: {
8836 struct file_upload_state *fus =
8837 (
struct file_upload_state *) mp->
user_data;
8838 if (fus == NULL) break;
8839 if (mp->
status >= 0 && fus->fp != NULL) {
8841 fus->lfn, (int) fus->num_recd));
8842 } else {
8844
8845
8846
8847
8848 }
8849 if (fus->fp != NULL) fclose(fus->fp);
8853
8854 break;
8855 }
8856 case MG_EV_HTTP_MULTIPART_REQUEST_END: {
8858 "HTTP/1.1 200 OK\r\n"
8859 "Content-Type: text/plain\r\n"
8860 "Connection: close\r\n\r\n"
8861 "Ok.\r\n");
8863 break;
8864 }
8865 }
8866
8867#if MG_ENABLE_CALLBACK_USERDATA
8868 (void) user_data;
8869#endif
8870}
8871
8872#endif
8873#endif
8874
8877 struct mg_connect_opts opts,
const char *scheme1,
const char *scheme2,
8878 const char *scheme_ssl1, const char *scheme_ssl2, const char *url,
8881 unsigned int port_i = 0;
8882 int use_ssl = 0;
8883 struct mg_str scheme, query, fragment;
8884 char conn_addr_buf[2];
8885 char *conn_addr = conn_addr_buf;
8886
8888 &query, &fragment) != 0) {
8890 goto out;
8891 }
8892
8893
8894 if (query.
len > 0) path->
len += query.
len + 1;
8895
8896 if (scheme.
len == 0 ||
mg_vcmp(&scheme, scheme1) == 0 ||
8897 (scheme2 != NULL &&
mg_vcmp(&scheme, scheme2) == 0)) {
8898 use_ssl = 0;
8899 if (port_i == 0) port_i = 80;
8900 }
else if (
mg_vcmp(&scheme, scheme_ssl1) == 0 ||
8901 (scheme2 != NULL &&
mg_vcmp(&scheme, scheme_ssl2) == 0)) {
8902 use_ssl = 1;
8903 if (port_i == 0) port_i = 443;
8904 } else {
8905 goto out;
8906 }
8907
8908 mg_asprintf(&conn_addr,
sizeof(conn_addr_buf),
"tcp://%.*s:%u",
8909 (
int) host->
len, host->
p, port_i);
8910 if (conn_addr == NULL) goto out;
8911
8912 LOG(
LL_DEBUG, (
"%s use_ssl? %d %s", url, use_ssl, conn_addr));
8913 if (use_ssl) {
8914#if MG_ENABLE_SSL
8915
8916
8917
8918
8919
8920 if (opts.ssl_ca_cert == NULL) {
8921 opts.ssl_ca_cert = "*";
8922 }
8923#else
8925 goto out;
8926#endif
8927 }
8928
8930 opts)) != NULL) {
8932 }
8933
8934out:
8935 if (conn_addr != NULL && conn_addr != conn_addr_buf)
MG_FREE(conn_addr);
8936 return nc;
8937}
8938
8941 struct mg_connect_opts opts,
const char *url,
const char *extra_headers,
8942 const char *post_data) {
8948 NULL, "https", NULL, url, &path, &user, &host);
8949
8950 if (nc == NULL) {
8951 return NULL;
8952 }
8953
8957 }
8958
8959 if (post_data == NULL) post_data = "";
8960 if (extra_headers == NULL) extra_headers = "";
8961 if (path.len == 0) path =
mg_mk_str(
"/");
8963
8964 mg_printf(nc,
"%s %.*s HTTP/1.1\r\nHost: %.*s\r\nContent-Length: %" SIZE_T_FMT
8965 "\r\n%.*s%s\r\n%s",
8966 (post_data[0] == '\0' ? "GET" : "POST"), (int) path.len, path.p,
8967 (int) (path.p - host.p), host.p, strlen(post_data), (int) auth.len,
8968 (auth.
buf == NULL ?
"" : auth.
buf), extra_headers, post_data);
8969
8971 return nc;
8972}
8973
8976 const char *url, const char *extra_headers, const char *post_data) {
8978 memset(&opts, 0, sizeof(opts));
8980 extra_headers, post_data);
8981}
8982
8985 size_t file_name_len,
const char **
data,
8986 size_t *data_len) {
8987 static const char cd[] = "Content-Disposition: ";
8988 size_t hl,
bl,
n, ll, pos, cdl =
sizeof(cd) - 1;
8989 int shl;
8990
8991 if (buf == NULL || buf_len <= 0) return 0;
8993 hl = shl;
8994 if (buf[0] != '-' || buf[1] != '-' || buf[2] == '\n') return 0;
8995
8996
8998
8999
9004 header.
p = buf +
n + cdl;
9005 header.
len = ll - (cdl + 2);
9006 {
9009
9013 }
9014 }
9015 {
9018
9022 }
9023 }
9024 }
9025 }
9026
9027
9028 for (pos = hl; pos + (
bl - 2) < buf_len; pos++) {
9029 if (buf[pos] ==
'-' && !strncmp(buf, &buf[pos],
bl - 2)) {
9030 if (data_len != NULL) *data_len = (pos - 2) - hl;
9031 if (
data != NULL) *
data = buf + hl;
9032 return pos;
9033 }
9034 }
9035
9036 return 0;
9037}
9038
9040 const char *uri_path,
9045
9046 if (nc == NULL) return;
9048 if (new_ep == NULL) return;
9049
9051 if (pd == NULL) pd = mg_http_create_proto_data(nc);
9055 new_ep->auth_file = strdup(opts.
auth_file);
9056 }
9058#if MG_ENABLE_CALLBACK_USERDATA
9060#endif
9063}
9064
9069
9072 || ev == MG_EV_HTTP_MULTIPART_REQUEST
9073#endif
9074 ) {
9077 if (ep != NULL) {
9078#if MG_ENABLE_FILESYSTEM && !MG_DISABLE_HTTP_DIGEST_AUTH
9082 return;
9083 }
9084#endif
9086#if MG_ENABLE_CALLBACK_USERDATA
9087 user_data = ep->user_data;
9088#endif
9089 }
9090 }
9092 user_data, ev, hm);
9093}
9094
9097 void *user_data)) {
9099 memset(&opts, 0, sizeof(opts));
9100#if MG_ENABLE_CALLBACK_USERDATA
9102#endif
9104}
9105
9106#endif
9107#ifdef MG_MODULE_LINES
9108#line 1 "mongoose/src/mg_http_cgi.c"
9109#endif
9110
9111
9112
9113
9114
9115#ifndef _WIN32
9116#include <signal.h>
9117#endif
9118
9119#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_CGI
9120
9121#ifndef MG_MAX_CGI_ENVIR_VARS
9122#define MG_MAX_CGI_ENVIR_VARS 64
9123#endif
9124
9125#ifndef MG_ENV_EXPORT_TO_CGI
9126#define MG_ENV_EXPORT_TO_CGI "MONGOOSE_CGI"
9127#endif
9128
9129#define MG_F_HTTP_CGI_PARSE_HEADERS MG_F_USER_1
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9147};
9148
9149#ifdef _WIN32
9150struct mg_threadparam {
9151 sock_t s;
9152 HANDLE hPipe;
9153};
9154
9155static int mg_wait_until_ready(sock_t sock, int for_read) {
9156 fd_set set;
9157 FD_ZERO(&set);
9158 FD_SET(sock, &set);
9159 return select(sock + 1, for_read ? &
set : 0, for_read ? 0 : &
set, 0, 0) == 1;
9160}
9161
9162static void *mg_push_to_stdin(void *arg) {
9163 struct mg_threadparam *tp = (struct mg_threadparam *) arg;
9164 int n, sent, stop = 0;
9166 char buf[BUFSIZ];
9167
9168 while (!stop && mg_wait_until_ready(tp->s, 1) &&
9169 (
n = recv(tp->s, buf,
sizeof(buf), 0)) > 0) {
9170 if (
n == -1 && GetLastError() == WSAEWOULDBLOCK)
continue;
9171 for (sent = 0; !stop && sent <
n; sent +=
k) {
9172 if (!WriteFile(tp->hPipe, buf + sent,
n - sent, &
k, 0)) stop = 1;
9173 }
9174 }
9175 DBG((
"%s",
"FORWARED EVERYTHING TO CGI"));
9176 CloseHandle(tp->hPipe);
9178 return NULL;
9179}
9180
9181static void *mg_pull_from_stdout(void *arg) {
9182 struct mg_threadparam *tp = (struct mg_threadparam *) arg;
9183 int k = 0, stop = 0;
9185 char buf[BUFSIZ];
9186
9187 while (!stop && ReadFile(tp->hPipe, buf,
sizeof(buf), &
n, NULL)) {
9188 for (sent = 0; !stop && sent <
n; sent +=
k) {
9189 if (mg_wait_until_ready(tp->s, 0) &&
9190 (
k = send(tp->s, buf + sent,
n - sent, 0)) <= 0)
9191 stop = 1;
9192 }
9193 }
9194 DBG((
"%s",
"EOF FROM CGI"));
9195 CloseHandle(tp->hPipe);
9196 shutdown(tp->s, 2);
9199 return NULL;
9200}
9201
9202static void mg_spawn_stdio_thread(sock_t sock, HANDLE hPipe,
9203 void *(*func)(void *)) {
9204 struct mg_threadparam *tp = (
struct mg_threadparam *)
MG_MALLOC(
sizeof(*tp));
9205 if (tp != NULL) {
9206 tp->s = sock;
9207 tp->hPipe = hPipe;
9209 }
9210}
9211
9212static void mg_abs_path(const char *utf8_path, char *abs_path, size_t len) {
9215 GetFullPathNameW(buf,
ARRAY_SIZE(buf2), buf2, NULL);
9216 WideCharToMultiByte(CP_UTF8, 0, buf2, wcslen(buf2) + 1, abs_path, len, 0, 0);
9217}
9218
9220 const char *env, const char *envp[],
9221 const char *dir, sock_t sock) {
9222 STARTUPINFOW si;
9223 PROCESS_INFORMATION
pi;
9224 HANDLE a[2], b[2], me = GetCurrentProcess();
9228 DWORD flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;
9230
9231 memset(&si, 0, sizeof(si));
9232 memset(&
pi, 0,
sizeof(
pi));
9233
9234 si.cb = sizeof(si);
9235 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
9236 si.wShowWindow = SW_HIDE;
9237 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
9238
9239 CreatePipe(&a[0], &a[1], NULL, 0);
9240 CreatePipe(&b[0], &b[1], NULL, 0);
9241 DuplicateHandle(me, a[0], me, &si.hStdInput, 0,
TRUE, flags);
9242 DuplicateHandle(me, b[1], me, &si.hStdOutput, 0,
TRUE, flags);
9243
9244 if (interp == NULL && (
fp =
mg_fopen(cmd,
"r")) != NULL) {
9245 buf[0] = buf[1] = '\0';
9246 fgets(buf,
sizeof(buf),
fp);
9247 buf[sizeof(buf) - 1] = '\0';
9248 if (buf[0] == '#' && buf[1] == '!') {
9249 interp = buf + 2;
9250
9251 while (*interp != '\0' && isspace(*(unsigned char *) interp)) {
9252 interp++;
9253 }
9254 }
9256 }
9257
9258 snprintf(buf, sizeof(buf), "%s/%s", dir, cmd);
9260
9262 to_wchar(dir, full_dir,
ARRAY_SIZE(full_dir));
9263
9264 if (interp != NULL) {
9266 snprintf(cmdline, sizeof(cmdline), "%s \"%s\"", buf4, buf2);
9267 } else {
9268 snprintf(cmdline, sizeof(cmdline), "\"%s\"", buf2);
9269 }
9271
9272 if (CreateProcessW(NULL, wcmd, NULL, NULL,
TRUE, CREATE_NEW_PROCESS_GROUP,
9273 (
void *) env, full_dir, &si, &
pi) != 0) {
9274 mg_spawn_stdio_thread(sock, a[1], mg_push_to_stdin);
9275 mg_spawn_stdio_thread(sock, b[0], mg_pull_from_stdout);
9276
9277 CloseHandle(si.hStdOutput);
9278 CloseHandle(si.hStdInput);
9279
9280 CloseHandle(
pi.hThread);
9281 CloseHandle(
pi.hProcess);
9282 } else {
9283 CloseHandle(a[1]);
9284 CloseHandle(b[0]);
9286 }
9287 DBG((
"CGI command: [%ls] -> %p", wcmd,
pi.hProcess));
9288
9289
9290 (void) envp;
9291 return (
pi.hProcess != NULL);
9292}
9293#else
9295 const char *env, const char *envp[],
9296 const char *dir, sock_t sock) {
9297 char buf[500];
9298 pid_t pid = fork();
9299 (void) env;
9300
9301 if (pid == 0) {
9302
9303
9304
9305
9306 int tmp = chdir(dir);
9307 (void) tmp;
9308 (void) dup2(sock, 0);
9309 (void) dup2(sock, 1);
9311
9312
9313
9314
9315
9316
9317
9318 signal(SIGCHLD, SIG_DFL);
9319
9320 if (interp == NULL) {
9321 execle(cmd, cmd, (char *) 0, envp);
9322 } else {
9323 execle(interp, interp, cmd, (char *) 0, envp);
9324 }
9325 snprintf(buf, sizeof(buf),
9326 "Status: 500\r\n\r\n"
9327 "500 Server Error: %s%s%s: %s",
9328 interp == NULL ? "" : interp, interp == NULL ? "" : " ", cmd,
9329 strerror(errno));
9330 send(1, buf, strlen(buf), 0);
9331 _exit(EXIT_FAILURE);
9332 }
9333
9334 return (pid != 0);
9335}
9336#endif
9337
9338
9339
9340
9341
9344 char *added = block->
buf + block->
len;
9345 va_list ap;
9346
9347
9348 space =
sizeof(block->
buf) - (block->
len + 2);
9349 if (space > 0) {
9350
9351 va_start(ap, fmt);
9352 n = vsnprintf(added, (
size_t) space, fmt, ap);
9353 va_end(ap);
9354
9355
9356 if (
n > 0 &&
n + 1 < space &&
9358
9360
9361 block->
len +=
n + 1;
9362 }
9363 }
9364
9365 return added;
9366}
9367
9369 const char *s;
9371}
9372
9374 const char *prog,
9375 const struct mg_str *path_info,
9379 const char *s;
9383 char buf[100];
9384 size_t path_info_len = path_info != NULL ? path_info->
len : 0;
9385
9386 blk->len =
blk->nvars = 0;
9388
9389 if ((s = getenv("SERVER_NAME")) != NULL) {
9391 } else {
9394 }
9398
9399
9403
9405
9408 hm->query_string.
p);
9409
9415
9416 s = hm->
uri.
p + hm->
uri.
len - path_info_len - 1;
9417 if (*s == '/') {
9418 const char *base_name = strrchr(prog, DIRSEP);
9420 (base_name != NULL ? base_name + 1 : prog));
9421 } else {
9423 }
9425
9426 if (path_info != NULL && path_info->
len > 0) {
9428
9429 mg_addenv(
blk,
"PATH_TRANSLATED=%.*s", (
int) path_info->
len, path_info->
p);
9430 }
9431
9432#if MG_ENABLE_SSL
9434#else
9436#endif
9437
9439 NULL) {
9441 }
9442
9446 }
9447
9449 NULL) {
9451 }
9452
9459
9460#ifdef _WIN32
9467#else
9469#endif
9470
9471
9476
9477
9478 for (; *
p !=
'=' && *
p !=
'\0';
p++) {
9479 if (*
p ==
'-') *
p =
'_';
9480 *
p = (char) toupper(*(
unsigned char *)
p);
9481 }
9482 }
9483
9484 blk->vars[
blk->nvars++] = NULL;
9485 blk->buf[
blk->len++] =
'\0';
9486}
9487
9489 void *ev_data
MG_UD_ARG(
void *user_data)) {
9490#if !MG_ENABLE_CALLBACK_USERDATA
9492#endif
9494 (void) ev_data;
9495
9496 if (nc == NULL) {
9497
9499 return;
9500 }
9501
9502 switch (ev) {
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517 if (nc->
flags & MG_F_HTTP_CGI_PARSE_HEADERS) {
9520
9521 if (
len == 0)
break;
9525 } else {
9530 mg_printf(nc,
"%s",
"HTTP/1.1 302 Moved\r\n");
9533 } else {
9534 mg_printf(nc,
"%s",
"HTTP/1.1 200 OK\r\n");
9535 }
9536 }
9537 nc->
flags &= ~MG_F_HTTP_CGI_PARSE_HEADERS;
9538 }
9539 if (!(nc->
flags & MG_F_HTTP_CGI_PARSE_HEADERS)) {
9541 }
9542 break;
9544 DBG((
"%p CLOSE", cgi_nc));
9547 break;
9548 }
9549}
9550
9552 const struct mg_str *path_info,
9557 const char *p;
9558 sock_t fds[2];
9559
9560 DBG((
"%p [%s]",
nc, prog));
9562
9563
9564
9565
9566
9567 if ((p = strrchr(prog, DIRSEP)) == NULL) {
9568 snprintf(dir, sizeof(dir), "%s", ".");
9569 } else {
9570 snprintf(dir, sizeof(dir), "%.*s", (int) (p - prog), prog);
9571 prog = p + 1;
9572 }
9573
9576 return;
9577 }
9578
9579#ifndef _WIN32
9580 struct sigaction sa;
9581
9582 sigemptyset(&sa.sa_mask);
9583 sa.sa_handler = SIG_IGN;
9584 sa.sa_flags = 0;
9585 sigaction(SIGCHLD, &sa, NULL);
9586#endif
9587
9589 fds[1]) != 0) {
9594#if !MG_ENABLE_CALLBACK_USERDATA
9596#endif
9597 nc->
flags |= MG_F_HTTP_CGI_PARSE_HEADERS;
9598
9601 }
9603 } else {
9606 }
9607
9608#ifndef _WIN32
9610#endif
9611}
9612
9614 if (
d == NULL)
return;
9615 if (
d->cgi_nc != NULL) {
9617 d->cgi_nc->user_data = NULL;
9618 }
9619 memset(
d, 0,
sizeof(*
d));
9620}
9621
9622#endif
9623#ifdef MG_MODULE_LINES
9624#line 1 "mongoose/src/mg_http_ssi.c"
9625#endif
9626
9627
9628
9629
9630
9631#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_SSI && MG_ENABLE_FILESYSTEM
9632
9634 const char *path, FILE *
fp,
int include_level,
9636
9638 char buf[BUFSIZ];
9640 while ((
n = mg_fread(buf, 1,
sizeof(buf),
fp)) > 0) {
9642 }
9643}
9644
9645#if 0
9647 const char *ssi, char *tag, int include_level,
9651
9652
9653
9654
9655
9656 if (sscanf(tag,
" virtual=\"%[^\"]\"",
file_name) == 1) {
9657
9659 }
else if (sscanf(tag,
" abspath=\"%[^\"]\"",
file_name) == 1) {
9660
9661
9662
9663
9664 snprintf(path,
sizeof(path),
"%s",
file_name);
9665 }
else if (sscanf(tag,
" file=\"%[^\"]\"",
file_name) == 1 ||
9666 sscanf(tag,
" \"%[^\"]\"",
file_name) == 1) {
9667
9668 snprintf(path, sizeof(path), "%s", ssi);
9669 if ((p = strrchr(path, DIRSEP)) != NULL) {
9670 p[1] = '\0';
9671 }
9672 snprintf(path + strlen(path),
sizeof(path) - strlen(path),
"%s",
file_name);
9673 } else {
9674 mg_printf(nc,
"Bad SSI #include: [%s]", tag);
9675 return;
9676 }
9677
9679 mg_printf(nc,
"SSI include error: mg_fopen(%s): %s", path,
9681 } else {
9684 0) {
9686 } else {
9688 }
9690 }
9691}
9692#endif
9693
9694#if MG_ENABLE_HTTP_SSI_EXEC
9696 char cmd[BUFSIZ];
9698
9699 if (sscanf(tag, " \"%[^\"]\"", cmd) != 1) {
9700 mg_printf(nc,
"Bad SSI #exec: [%s]", tag);
9701 }
else if ((
fp = popen(cmd,
"r")) == NULL) {
9703 } else {
9706 }
9707}
9708#endif
9709
9710
9711
9712
9713
9714#if 0
9716 const char *path, FILE *
fp,
int include_level,
9721#if MG_ENABLE_HTTP_SSI_EXEC
9723#endif
9724 char buf[BUFSIZ], *
p = buf + btag.
len;
9725 int ch,
len, in_ssi_tag;
9726
9727 if (include_level > 10) {
9728 mg_printf(nc,
"SSI #include level is too deep (%s)", path);
9729 return;
9730 }
9731
9732 in_ssi_tag =
len = 0;
9733 while ((ch = fgetc(
fp)) != EOF) {
9734 if (in_ssi_tag && ch ==
'>' && buf[
len - 1] ==
'-' && buf[
len - 2] ==
'-') {
9736 in_ssi_tag = 0;
9737
9738
9740 while (
i > 0 && buf[
i] ==
' ') {
9742 }
9743
9744
9745 if (strncmp(
p, d_include.
p, d_include.
len) == 0) {
9746 mg_do_ssi_include(nc, hm, path,
p + d_include.
len + 1, include_level,
9747 opts);
9748 }
else if (strncmp(
p, d_call.
p, d_call.
len) == 0) {
9750 memset(&cctx, 0, sizeof(cctx));
9751 cctx.req = hm;
9755 (void *) cctx.arg.p);
9757#if MG_ENABLE_HTTP_SSI_EXEC
9758 }
else if (strncmp(p, d_exec.
p, d_exec.
len) == 0) {
9760#endif
9761 } else {
9762
9763 }
9764 len = 0;
9765 } else if (ch == '<') {
9766 in_ssi_tag = 1;
9767 if (len > 0) {
9768 mg_send(nc, buf, (
size_t) len);
9769 }
9770 len = 0;
9771 buf[len++] = ch & 0xff;
9772 } else if (in_ssi_tag) {
9773 if (len == (
int) btag.
len && strncmp(buf, btag.
p, btag.
len) != 0) {
9774
9775 in_ssi_tag = 0;
9776 } else if (len == (int) sizeof(buf) - 2) {
9777 mg_printf(nc,
"%s: SSI tag is too large", path);
9778 len = 0;
9779 }
9780 buf[len++] = ch & 0xff;
9781 } else {
9782 buf[len++] = ch & 0xff;
9783 if (len == (int) sizeof(buf)) {
9784 mg_send(nc, buf, (
size_t) len);
9785 len = 0;
9786 }
9787 }
9788 }
9789
9790
9791 if (len > 0) {
9792 mg_send(nc, buf, (
size_t) len);
9793 }
9794}
9795
9798 const char *path,
9802 DBG((
"%p %s", nc, path));
9803
9806 } else {
9808
9812 "Content-Type: %.*s\r\n"
9813 "Connection: close\r\n\r\n",
9818 }
9819}
9820#endif
9821
9822#endif
9823#ifdef MG_MODULE_LINES
9824#line 1 "mongoose/src/mg_http_webdav.c"
9825#endif
9826
9827
9828
9829
9830
9831#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBDAV
9832
9834 static const char *methods[] = {
9835 "PUT",
9836 "DELETE",
9837 "MKCOL",
9838 "PROPFIND",
9839 "MOVE"
9840#if MG_ENABLE_FAKE_DAVLOCK
9841 ,
9842 "LOCK",
9843 "UNLOCK"
9844#endif
9845 };
9847
9850 return 1;
9851 }
9852 }
9853
9854 return 0;
9855}
9856
9857static int mg_mkdir(
const char *path, uint32_t mode) {
9858#ifndef _WIN32
9859 return mkdir(path, mode);
9860#else
9861 (void) mode;
9862 return _mkdir(path);
9863#endif
9864}
9865
9867 cs_stat_t *stp) {
9868 char mtime[64];
9869 time_t t = stp->st_mtime;
9873 "<d:response>"
9874 "<d:href>%s</d:href>"
9875 "<d:propstat>"
9876 "<d:prop>"
9877 "<d:resourcetype>%s</d:resourcetype>"
9879 "</d:getcontentlength>"
9880 "<d:getlastmodified>%s</d:getlastmodified>"
9881 "</d:prop>"
9882 "<d:status>HTTP/1.1 200 OK</d:status>"
9883 "</d:propstat>"
9884 "</d:response>\n",
9885 name_esc.
p, S_ISDIR(stp->st_mode) ?
"<d:collection/>" :
"",
9886 (int64_t) stp->st_size, mtime);
9887 free((
void *) name_esc.
p);
9888}
9889
9893 static const char header[] =
9894 "HTTP/1.1 207 Multi-Status\r\n"
9895 "Connection: close\r\n"
9896 "Content-Type: text/xml; charset=utf-8\r\n\r\n"
9897 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
9898 "<d:multistatus xmlns:d='DAV:'>\n";
9899 static const char footer[] = "</d:multistatus>\n";
9901
9902
9903 if (S_ISDIR(stp->st_mode) &&
9905 mg_printf(nc,
"%s",
"HTTP/1.1 403 Directory Listing Denied\r\n\r\n");
9906 } else {
9908 mg_send(nc, header,
sizeof(header) - 1);
9909 snprintf(uri,
sizeof(uri),
"%.*s", (
int) hm->
uri.
len, hm->
uri.
p);
9911 if (S_ISDIR(stp->st_mode) && (depth == NULL ||
mg_vcmp(depth,
"0") != 0)) {
9913 }
9914 mg_send(nc, footer,
sizeof(footer) - 1);
9916 }
9917}
9918
9919#if MG_ENABLE_FAKE_DAVLOCK
9920
9921
9922
9923
9924
9925
9926
9927
9928
9929
9930
9932 static const char *reply =
9933 "HTTP/1.1 207 Multi-Status\r\n"
9934 "Connection: close\r\n"
9935 "Content-Type: text/xml; charset=utf-8\r\n\r\n"
9936 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
9937 "<d:multistatus xmlns:d='DAV:'>\n"
9938 "<D:lockdiscovery>\n"
9939 "<D:activelock>\n"
9940 "<D:locktoken>\n"
9941 "<D:href>\n"
9942 "opaquelocktoken:%s%u"
9943 "</D:href>"
9944 "</D:locktoken>"
9945 "</D:activelock>\n"
9946 "</D:lockdiscovery>"
9947 "</d:multistatus>\n";
9950}
9951#endif
9952
9955 int status_code = 500;
9957 status_code = 415;
9958 }
else if (!
mg_mkdir(path, 0755)) {
9959 status_code = 201;
9960 } else if (errno == EEXIST) {
9961 status_code = 405;
9962 } else if (errno == EACCES) {
9963 status_code = 403;
9964 } else if (errno == ENOENT) {
9965 status_code = 409;
9966 } else {
9967 status_code = 500;
9968 }
9970}
9971
9973 const char *dir) {
9975 struct dirent *dp;
9976 cs_stat_t st;
9978
9979 if ((dirp = opendir(dir)) == NULL) return 0;
9980
9981 while ((dp = readdir(dirp)) != NULL) {
9983 continue;
9984 }
9985 snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
9987 if (S_ISDIR(st.st_mode)) {
9989 } else {
9990 remove(path);
9991 }
9992 }
9993 closedir(dirp);
9995
9996 return 1;
9997}
9998
10003 if (dest == NULL) {
10005 } else {
10006 const char *
p = (
char *) memchr(dest->
p,
'/', dest->
len);
10007 if (
p != NULL &&
p[1] ==
'/' &&
10008 (
p = (
char *) memchr(
p + 2,
'/', dest->
p + dest->
len -
p)) != NULL) {
10011 (
int) (dest->
p + dest->
len -
p),
p);
10012 if (rename(path, buf) == 0) {
10014 } else {
10016 }
10017 } else {
10019 }
10020 }
10021}
10022
10025 const char *path) {
10026 cs_stat_t st;
10027 if (
mg_stat(path, &st) != 0) {
10029 } else if (S_ISDIR(st.st_mode)) {
10032 } else if (remove(path) == 0) {
10034 } else {
10036 }
10037}
10038
10039
10041 const char *s;
10042
10043
10044 for (s = path + 1; *s != '\0'; s++) {
10045 if (*s == '/') {
10047 cs_stat_t st;
10048 snprintf(buf, sizeof(buf), "%.*s", (int) (s - path), path);
10049 buf[sizeof(buf) - 1] = '\0';
10051 return -1;
10052 }
10053 }
10054 }
10055
10056 return 1;
10057}
10058
10062 cs_stat_t st;
10064 int rc, status_code =
mg_stat(path, &st) == 0 ? 200 : 201;
10065
10068 mg_printf(nc,
"HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code);
10069 } else if (rc == -1) {
10071 } else if (cl_hdr == NULL) {
10075 } else {
10077 int64_t r1 = 0, r2 = 0;
10080 pd->
file.
cl = to64(cl_hdr->
p);
10081 if (range_hdr != NULL &&
10083 status_code = 206;
10084 fseeko(pd->
file.
fp, r1, SEEK_SET);
10085 pd->
file.
cl = r2 > r1 ? r2 - r1 + 1 : pd->
file.
cl - r1;
10086 }
10087 mg_printf(nc,
"HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code);
10088
10091 }
10092}
10093
10094#endif
10095#ifdef MG_MODULE_LINES
10096#line 1 "mongoose/src/mg_http_websocket.c"
10097#endif
10098
10099
10100
10101
10102
10103#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBSOCKET
10104
10105
10106
10107#ifndef MG_WEBSOCKET_PING_INTERVAL_SECONDS
10108#define MG_WEBSOCKET_PING_INTERVAL_SECONDS 5
10109#endif
10110
10111#define FLAGS_MASK_FIN (1 << 7)
10112#define FLAGS_MASK_OP 0x0f
10113
10115 return (flags & FLAGS_MASK_FIN) == 0 ||
10117}
10118
10120 return (flags & FLAGS_MASK_FIN) == 0 &&
10122}
10123
10124static int mg_is_ws_control_frame(unsigned char flags) {
10125 unsigned char op = (flags & FLAGS_MASK_OP);
10128}
10129
10132 if (wsm->
flags & 0x8) {
10134 } else {
10136 }
10137}
10138
10139static struct mg_ws_proto_data *mg_ws_get_proto_data(
struct mg_connection *nc) {
10141 return (htd != NULL ? &htd->ws_data : NULL);
10142}
10143
10144
10145
10146
10147
10149 size_t len) {
10150 if ((int) len == ~0) {
10151 len = strlen((
const char *)
data);
10152 }
10155}
10156
10158
10159 uint64_t
i, data_len = 0, frame_len = 0, new_data_len = nc->
recv_mbuf.
len,
10160 len, mask_len = 0, header_len = 0;
10161 struct mg_ws_proto_data *wsd = mg_ws_get_proto_data(nc);
10162 unsigned char *new_data = (
unsigned char *) nc->
recv_mbuf.
buf,
10164 uint8_t flags;
10165 int ok, reass;
10166
10167 if (wsd->reass_len > 0) {
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178 size_t existing_len = wsd->reass_len;
10179 assert(new_data_len >= existing_len);
10180
10181 new_data += existing_len;
10182 new_data_len -= existing_len;
10183 }
10184
10185 flags = new_data[0];
10186
10189
10190 if (reass && mg_is_ws_control_frame(flags)) {
10191
10192
10193
10194
10195 mg_ws_close(nc, "fragmented control frames are illegal", ~0);
10196 return 0;
10197 } else if (new_data_len > 0 && !reass && !mg_is_ws_control_frame(flags) &&
10198 wsd->reass_len > 0) {
10199
10200
10201
10202
10203 mg_ws_close(nc, "non-continuation in the middle of a fragmented message",
10204 ~0);
10205 return 0;
10206 }
10207
10208 if (new_data_len >= 2) {
10209 len = new_data[1] & 0x7f;
10210 mask_len = new_data[1] & FLAGS_MASK_FIN ? 4 : 0;
10211 if (len < 126 && new_data_len >= mask_len) {
10212 data_len = len;
10213 header_len = 2 + mask_len;
10214 } else if (len == 126 && new_data_len >= 4 + mask_len) {
10215 header_len = 4 + mask_len;
10216 data_len = ntohs(*(uint16_t *) &new_data[2]);
10217 } else if (new_data_len >= 10 + mask_len) {
10218 header_len = 10 + mask_len;
10219 data_len = (((uint64_t) ntohl(*(uint32_t *) &new_data[2])) << 32) +
10220 ntohl(*(uint32_t *) &new_data[6]);
10221 }
10222 }
10223
10224 frame_len = header_len + data_len;
10225 ok = (frame_len > 0 && frame_len <= new_data_len);
10226
10227
10228 if (frame_len < header_len || frame_len < data_len) {
10229 ok = 0;
10230 mg_ws_close(nc, "overflowed message", ~0);
10231 }
10232
10233 if (ok) {
10234 size_t cleanup_len = 0;
10236
10237 wsm.
size = (size_t) data_len;
10238 wsm.
data = new_data + header_len;
10240
10241
10242 if (mask_len > 0) {
10243 for (
i = 0;
i < data_len;
i++) {
10244 new_data[
i + header_len] ^= (new_data + header_len - mask_len)[
i % 4];
10245 }
10246 }
10247
10248 if (reass) {
10249
10250
10252
10253
10254
10255
10256 new_data += 1;
10257 wsd->reass_len = 1 ;
10258 }
10259
10260
10261 memmove(new_data, wsm.
data,
e - wsm.
data);
10262 wsd->reass_len += wsm.
size;
10264
10265 if (
flags & FLAGS_MASK_FIN) {
10266
10269 wsm.
size = wsd->reass_len - 1 ;
10270 cleanup_len = wsd->reass_len;
10271 wsd->reass_len = 0;
10272
10273
10276 }
10277 } else {
10278
10279
10280
10281
10282
10283 cleanup_len = (size_t) frame_len;
10284
10285
10286 switch (
flags & FLAGS_MASK_OP) {
10289 break;
10290
10292 mg_ws_close(nc, wsm.
data, wsm.
size);
10293 break;
10294 }
10295
10296
10298
10299
10304 }
10305 }
10306
10307 return ok;
10308}
10309
10313};
10314
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331#if MG_DISABLE_WS_RANDOM_MASK
10333#else
10334 if (sizeof(long) >= 4) {
10335 mask = (uint32_t) rand();
10336 } else if (sizeof(long) == 2) {
10337 mask = (uint32_t) rand() << 16 | (uint32_t) rand();
10338 }
10339#endif
10341}
10342
10345 int header_len;
10346 unsigned char header[10];
10347
10348 header[0] =
10350 if (len < 126) {
10351 header[1] = (unsigned char) len;
10352 header_len = 2;
10353 } else if (len < 65535) {
10354 uint16_t tmp = htons((uint16_t) len);
10355 header[1] = 126;
10356 memcpy(&header[2], &tmp, sizeof(tmp));
10357 header_len = 4;
10358 } else {
10359 uint32_t tmp;
10360 header[1] = 127;
10361 tmp = htonl((uint32_t)((uint64_t) len >> 32));
10362 memcpy(&header[2], &tmp, sizeof(tmp));
10363 tmp = htonl((uint32_t)(len & 0xffffffff));
10364 memcpy(&header[6], &tmp, sizeof(tmp));
10365 header_len = 10;
10366 }
10367
10368
10370 header[1] |= 1 << 7;
10371 mg_send(nc, header, header_len);
10375 } else {
10376 mg_send(nc, header, header_len);
10378 }
10379}
10380
10383 if (ctx->
pos == 0)
return;
10386 }
10387}
10388
10390 size_t len) {
10392 DBG((
"%p %d %d", nc, op, (
int) len));
10395
10397
10400 }
10401}
10402
10404 const struct mg_str *strv,
int strvcnt) {
10407 int len = 0;
10408 for (
i = 0;
i < strvcnt;
i++) {
10409 len += strv[
i].
len;
10410 }
10411
10413
10414 for (
i = 0;
i < strvcnt;
i++) {
10416 }
10417
10419
10422 }
10423}
10424
10426 const char *fmt, ...) {
10428 va_list ap;
10429 int len;
10430
10431 va_start(ap, fmt);
10432 if ((len =
mg_avprintf(&buf,
sizeof(mem), fmt, ap)) > 0) {
10434 }
10435 va_end(ap);
10436
10437 if (buf != mem && buf != NULL) {
10439 }
10440}
10441
10443 void *ev_data
MG_UD_ARG(
void *user_data)) {
10445
10446 switch (ev) {
10448 do {
10450 break;
10452
10453 {
10454 time_t now = *(time_t *) ev_data;
10458 }
10459 }
10460 break;
10461 default:
10462 break;
10463 }
10464#if MG_ENABLE_CALLBACK_USERDATA
10465 (void) user_data;
10466#endif
10467}
10468
10469#ifndef MG_EXT_SHA1
10471 const size_t *msg_lens, uint8_t *digest) {
10475 for (
i = 0;
i < num_msgs;
i++) {
10477 }
10479}
10480#else
10481extern void mg_hash_sha1_v(
size_t num_msgs,
const uint8_t *msgs[],
10482 const size_t *msg_lens, uint8_t *digest);
10483#endif
10484
10488 static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
10489 const uint8_t *msgs[2] = {(
const uint8_t *)
key->p, (
const uint8_t *) magic};
10490 const size_t msg_lens[2] = {
key->len, 36};
10491 unsigned char sha[20];
10492 char b64_sha[30];
10494
10498 "HTTP/1.1 101 Switching Protocols\r\n"
10499 "Upgrade: websocket\r\n"
10500 "Connection: Upgrade\r\n");
10501
10503 if (s != NULL) {
10504 mg_printf(nc,
"Sec-WebSocket-Protocol: %.*s\r\n", (
int) s->
len, s->
p);
10505 }
10506 mg_printf(nc,
"Sec-WebSocket-Accept: %s%s", b64_sha,
"\r\n\r\n");
10507
10508 DBG((
"%p %.*s %s", nc, (
int)
key->len,
key->p, b64_sha));
10509}
10510
10512 const char *host, const char *protocol,
10513 const char *extra_headers) {
10515 NULL);
10516}
10517
10519 const char *host, const char *protocol,
10520 const char *extra_headers, const char *user,
10521 const char *pass) {
10525}
10526
10528 const struct mg_str path,
10529 const struct mg_str host,
10530 const struct mg_str protocol,
10531 const struct mg_str extra_headers,
10532 const struct mg_str user,
10533 const struct mg_str pass) {
10536 uint32_t nonce[4];
10542
10544 if (user.
len > 0) {
10546 }
10547
10548
10549
10550
10551
10552
10553
10555 "GET %.*s HTTP/1.1\r\n"
10556 "Upgrade: websocket\r\n"
10557 "Connection: Upgrade\r\n"
10558 "%.*s"
10559 "Sec-WebSocket-Version: 13\r\n"
10560 "Sec-WebSocket-Key: %s\r\n",
10561 (
int) path.
len, path.
p, (
int) auth.len,
10562 (auth.buf == NULL ?
"" : auth.
buf),
key);
10563
10564
10565 if (host.
len > 0) {
10566 int host_len = (int) (path.
p - host.
p);
10567 mg_printf(nc,
"Host: %.*s\r\n", host_len, host.
p);
10568 }
10569 if (protocol.
len > 0) {
10570 mg_printf(nc,
"Sec-WebSocket-Protocol: %.*s\r\n", (
int) protocol.
len,
10572 }
10573 if (extra_headers.
len > 0) {
10574 mg_printf(nc,
"%.*s", (
int) extra_headers.
len, extra_headers.
p);
10575 }
10577
10579
10581}
10582
10584 const char *extra_headers) {
10587 nc,
mg_mk_str(path), null_str , null_str ,
10588 mg_mk_str(extra_headers), null_str , null_str );
10589}
10590
10594 const char *extra_headers) {
10599 "ws", "https", "wss", url, &path, &user_info, &host);
10600 if (nc != NULL) {
10603 null_str);
10604 }
10605 return nc;
10606}
10607
10610 const char *url, const char *protocol, const char *extra_headers) {
10612 memset(&opts, 0, sizeof(opts));
10614 protocol, extra_headers);
10615}
10616#endif
10617#ifdef MG_MODULE_LINES
10618#line 1 "mongoose/src/mg_util.c"
10619#endif
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630#ifndef MAX
10631#define MAX(a, b) ((a) > (b) ? (a) : (b))
10632#endif
10633
10634const char *
mg_skip(
const char *s,
const char *
end,
const char *delims,
10637 while (s <
end && strchr(delims, *(
unsigned char *) s) == NULL) s++;
10639 while (s <
end && strchr(delims, *(
unsigned char *) s) != NULL) s++;
10640 return s;
10641}
10642
10643#if MG_ENABLE_FILESYSTEM && !defined(MG_USER_FILE_FUNCTIONS)
10644int mg_stat(
const char *path, cs_stat_t *st) {
10645#ifdef _WIN32
10648 DBG((
"[%ls] -> %d", wpath, _wstati64(wpath, st)));
10649 return _wstati64(wpath, st);
10650#else
10651 return stat(path, st);
10652#endif
10653}
10654
10655FILE *
mg_fopen(
const char *path,
const char *mode) {
10656#ifdef _WIN32
10660 return _wfopen(wpath, wmode);
10661#else
10662 return fopen(path, mode);
10663#endif
10664}
10665
10666int mg_open(
const char *path,
int flag,
int mode) {
10667#if defined(_WIN32) && !defined(WINCE)
10670 return _wopen(wpath, flag, mode);
10671#else
10672 return open(path, flag, mode);
10673#endif
10674}
10675
10676size_t mg_fread(
void *ptr,
size_t size,
size_t count, FILE *f) {
10677 return fread(ptr, size,
count, f);
10678}
10679
10680size_t mg_fwrite(
const void *ptr,
size_t size,
size_t count, FILE *f) {
10681 return fwrite(ptr, size,
count, f);
10682}
10683#endif
10684
10687}
10688
10691}
10692
10693#if MG_ENABLE_THREADS
10695#ifdef WINCE
10696 return (void *) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) f, p, 0, NULL);
10697#elif defined(_WIN32)
10698 return (void *) _beginthread((void(__cdecl *) (void *) ) f, 0, p);
10699#else
10700 pthread_t thread_id = (pthread_t) 0;
10701 pthread_attr_t attr;
10702
10703 (void) pthread_attr_init(&attr);
10704 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10705
10706#if defined(MG_STACK_SIZE) && MG_STACK_SIZE > 1
10707 (void) pthread_attr_setstacksize(&attr, MG_STACK_SIZE);
10708#endif
10709
10710 pthread_create(&thread_id, &attr, f, p);
10711 pthread_attr_destroy(&attr);
10712
10713 return (void *) thread_id;
10714#endif
10715}
10716#endif
10717
10718
10720#if defined(_WIN32) && !defined(WINCE)
10721 (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
10722#elif defined(__unix__)
10723 fcntl(sock, F_SETFD, FD_CLOEXEC);
10724#else
10725 (void) sock;
10726#endif
10727}
10728
10731 int is_v6;
10732 if (buf == NULL || len <= 0) return 0;
10733 memset(buf, 0, len);
10734#if MG_ENABLE_IPV6
10735 is_v6 = sa->
sa.sa_family == AF_INET6;
10736#else
10737 is_v6 = 0;
10738#endif
10740#if MG_ENABLE_IPV6
10741 const void *
addr = NULL;
10742 char *start = buf;
10743 socklen_t capacity = len;
10744 if (!is_v6) {
10746 } else {
10747 addr = (
void *) &sa->
sin6.sin6_addr;
10749 *buf = '[';
10750 start++;
10751 capacity--;
10752 }
10753 }
10755 goto cleanup;
10756 }
10757#elif defined(_WIN32) || MG_LWIP || (MG_NET_IF == MG_NET_IF_PIC32)
10758
10760 if (addr_str != NULL) {
10762 } else {
10763 goto cleanup;
10764 }
10765#else
10766 if (
inet_ntop(AF_INET, (
void *) &sa->
sin.sin_addr, buf, len) == NULL) {
10767 goto cleanup;
10768 }
10769#endif
10770 }
10772 int port = ntohs(sa->
sin.sin_port);
10774 int buf_len = strlen(buf);
10775 snprintf(buf + buf_len, len - (buf_len + 1), "%s:%d", (is_v6 ? "]" : ""),
10776 port);
10777 } else {
10778 snprintf(buf, len, "%d", port);
10779 }
10780 }
10781
10782 return strlen(buf);
10783
10784cleanup:
10785 *buf = '\0';
10786 return 0;
10787}
10788
10792 memset(&
sa, 0,
sizeof(
sa));
10795}
10796
10797#if MG_ENABLE_HEXDUMP
10798static int mg_hexdump_n(const void *buf, int len, char *dst, int dst_len,
10800 const unsigned char *p = (const unsigned char *) buf;
10801 char ascii[17] = "";
10803
10804 for (
i = 0;
i < len;
i++) {
10806 if (idx == 0) {
10807 if (
i > 0)
n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
" %s\n", ascii);
10808 n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
"%04x ",
i +
offset);
10809 }
10810 if (dst_len -
n < 0) {
10812 }
10813 n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
" %02x", p[
i]);
10814 ascii[idx] = p[
i] < 0x20 || p[
i] > 0x7e ?
'.' : p[
i];
10815 ascii[idx + 1] = '\0';
10816 }
10817
10818 while (
i++ % 16)
n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
"%s",
" ");
10819 n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
" %s\n", ascii);
10820
10822}
10823
10824int mg_hexdump(
const void *buf,
int len,
char *dst,
int dst_len) {
10825 return mg_hexdump_n(buf, len, dst, dst_len, 0);
10826}
10827
10828void mg_hexdumpf(FILE *
fp,
const void *buf,
int len) {
10829 char tmp[80];
10831 while (len > 0) {
10832 n = (len < 16 ? len : 16);
10833 mg_hexdump_n(((
const char *) buf) +
offset,
n, tmp,
sizeof(tmp),
offset);
10837 }
10838}
10839
10841 const void *buf, int num_bytes, int ev) {
10843 char src[60], dst[60];
10844 const char *tag = NULL;
10845 switch (ev) {
10847 tag = "<-";
10848 break;
10850 tag = "->";
10851 break;
10853 tag = "<A";
10854 break;
10856 tag = "C>";
10857 break;
10859 tag = "XX";
10860 break;
10861 }
10862 if (tag == NULL) return;
10863
10864 if (strcmp(path, "-") == 0) {
10866 } else if (strcmp(path, "--") == 0) {
10868#if MG_ENABLE_FILESYSTEM
10869 } else {
10871#endif
10872 }
10873 if (
fp == NULL)
return;
10874
10880 fprintf(
fp,
"%lu %p %s %s %s %d\n", (
unsigned long)
mg_time(), (
void *) nc,
10881 src, tag, dst, (int) num_bytes);
10882 if (num_bytes > 0) {
10883 mg_hexdumpf(
fp, buf, num_bytes);
10884 }
10885 if (
fp != stdout &&
fp != stderr) fclose(
fp);
10886}
10887#endif
10888
10890 static const int n = 1;
10891
10892 return ((
char *) &
n)[0] == 0;
10893}
10894
10896#ifndef WINCE
10897 return errno;
10898#else
10899
10900 return GetLastError();
10901#endif
10902}
10903
10907}
10908
10914}
10915
10917 struct mbuf *buf) {
10918 const char *header_prefix = "Authorization: Basic ";
10919 const char *header_suffix = "\r\n";
10920
10923
10924 mbuf_append(buf, header_prefix, strlen(header_prefix));
10925
10927 if (pass.
len > 0) {
10930 }
10932 mbuf_append(buf, header_suffix, strlen(header_suffix));
10933}
10934
10936 const struct
mg_str safe, unsigned int flags) {
10937 const char *hex =
10939 : "0123456789abcdef");
10943
10944 for (
i = 0;
i < src.len;
i++) {
10945 const unsigned char c = *((
const unsigned char *) src.p +
i);
10950 } else {
10954 }
10955 }
10959}
10960
10963}
10964#ifdef MG_MODULE_LINES
10965#line 1 "mongoose/src/mg_mqtt.c"
10966#endif
10967
10968
10969
10970
10971
10972#if MG_ENABLE_MQTT
10973
10974#include <string.h>
10975
10976
10977
10978
10979static uint16_t getu16(const char *p) {
10980 const uint8_t *up = (const uint8_t *) p;
10981 return (up[0] << 8) + up[1];
10982}
10983
10984static const char *scanto(
const char *p,
struct mg_str *s) {
10985 s->
len = getu16(p);
10987 return s->
p + s->
len;
10988}
10989
10991 uint8_t header;
10992 size_t len = 0, len_len = 0;
10993 const char *p, *
end, *eop = &io->
buf[io->
len];
10994 unsigned char lc = 0;
10995 int cmd;
10996
10997 if (io->
len < 2)
return MG_MQTT_ERROR_INCOMPLETE_MSG;
10998 header = io->
buf[0];
10999 cmd = header >> 4;
11000
11001
11002 len = len_len = 0;
11004 while (p < eop) {
11005 lc = *((const unsigned char *) p++);
11006 len += (lc & 0x7f) << 7 * len_len;
11007 len_len++;
11008 if (!(lc & 0x80)) break;
11009 if (len_len > 4) return MG_MQTT_ERROR_MALFORMED_MSG;
11010 }
11011
11013 if (lc & 0x80 ||
end > eop)
return MG_MQTT_ERROR_INCOMPLETE_MSG;
11014
11017
11018 switch (cmd) {
11021 if (p >
end - 4)
return MG_MQTT_ERROR_MALFORMED_MSG;
11025 p += 2;
11026 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11028 if (p >
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11030 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11032 }
11034 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11036 }
11038 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11040 }
11042 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11044 }
11045 if (p !=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11046
11048 ("%d %2x %d proto [%.*s] client_id [%.*s] will_topic [%.*s] "
11049 "will_msg [%.*s] user_name [%.*s] password [%.*s]",
11056 break;
11057 }
11059 if (
end - p < 2)
return MG_MQTT_ERROR_MALFORMED_MSG;
11061 break;
11067 if (
end - p < 2)
return MG_MQTT_ERROR_MALFORMED_MSG;
11069 p += 2;
11070 break;
11072 p = scanto(p, &mm->
topic);
11073 if (p >
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
11075 if (
end - p < 2)
return MG_MQTT_ERROR_MALFORMED_MSG;
11077 p += 2;
11078 }
11081 break;
11082 }
11084 if (
end - p < 2)
return MG_MQTT_ERROR_MALFORMED_MSG;
11086 p += 2;
11087
11088
11089
11090
11093 break;
11094 default:
11095
11096 break;
11097 }
11098
11101}
11102
11104 void *ev_data
MG_UD_ARG(
void *user_data)) {
11107 memset(&mm, 0, sizeof(mm));
11108
11110
11111 switch (ev) {
11114 break;
11116
11117 while (1) {
11120 if (
len == MG_MQTT_ERROR_MALFORMED_MSG) {
11121
11123 }
else if (
len == MG_MQTT_ERROR_INCOMPLETE_MSG) {
11124
11125
11128 LOG(
LL_ERROR, (
"%p recv buffer (%lu bytes) exceeds the limit "
11129 "%lu bytes, and not drained, closing",
11133 }
11134 } else {
11135
11138 }
11139 break;
11140 }
11141
11144 }
11145 break;
11146 }
11151 if (pd->keep_alive > 0 && pd->last_control_time > 0 &&
11152 (now - pd->last_control_time) > pd->keep_alive) {
11155 }
11156 break;
11157 }
11158 }
11159}
11160
11161static void mg_mqtt_proto_data_destructor(void *proto_data) {
11163}
11164
11165static struct mg_str mg_mqtt_next_topic_component(struct
mg_str *topic) {
11166 struct mg_str res = *topic;
11169 res.
len = (
c - topic->p);
11170 topic->len -= (res.
len + 1);
11171 topic->p += (res.
len + 1);
11172 } else {
11173 topic->len = 0;
11174 }
11175 return res;
11176}
11177
11178
11181 if (exp.
len == 0)
return 0;
11182 while (1) {
11183 ec = mg_mqtt_next_topic_component(&exp);
11184 tc = mg_mqtt_next_topic_component(&topic);
11185 if (ec.len == 0) {
11186 if (tc.len != 0) return 0;
11187 if (exp.
len == 0)
break;
11188 continue;
11189 }
11190 if (
mg_vcmp(&ec,
"+") == 0) {
11191 if (tc.len == 0 && topic.
len == 0)
return 0;
11192 continue;
11193 }
11194 if (
mg_vcmp(&ec,
"#") == 0) {
11195
11196 return (exp.
len == 0);
11197 }
11199 return 0;
11200 }
11201 }
11202 return (tc.len == 0 && topic.
len == 0);
11203}
11204
11207}
11208
11213}
11214
11215static void mg_send_mqtt_header(
struct mg_connection *nc, uint8_t cmd,
11216 uint8_t flags,
size_t len) {
11218 uint8_t buf[1 + sizeof(size_t)];
11219 uint8_t *vlen = &buf[1];
11220
11221 buf[0] = (cmd << 4) | flags;
11222
11223
11224 do {
11225 *vlen = len % 0x80;
11226 len /= 0x80;
11227 if (len > 0) *vlen |= 0x80;
11228 vlen++;
11229 } while (len > 0);
11230
11231 mg_send(nc, buf, vlen - buf);
11232 pd->last_control_time =
mg_time();
11233}
11234
11238}
11239
11243 uint16_t id_len = 0, wt_len = 0, wm_len = 0, user_len = 0, pw_len = 0;
11244 uint16_t netbytes;
11245 size_t total_len;
11246
11247 if (client_id != NULL) {
11248 id_len = strlen(client_id);
11249 }
11250
11251 total_len = 7 + 1 + 2 + 2 + id_len;
11252
11253 if (opts.user_name != NULL) {
11255 }
11256 if (opts.password != NULL) {
11258 }
11259 if (opts.will_topic != NULL && opts.will_message != NULL) {
11260 wt_len = strlen(opts.will_topic);
11261 wm_len = strlen(opts.will_message);
11263 }
11264 if (opts.keep_alive == 0) {
11265 opts.keep_alive = 60;
11266 }
11267
11269 total_len += 2 + wt_len + 2 + wm_len;
11270 }
11272 user_len = strlen(opts.user_name);
11273 total_len += 2 + user_len;
11274 }
11276 pw_len = strlen(opts.password);
11277 total_len += 2 + pw_len;
11278 }
11279
11281 mg_send(nc,
"\00\04MQTT\04", 7);
11283
11284 netbytes = htons(opts.keep_alive);
11286
11287 netbytes = htons(id_len);
11289 mg_send(nc, client_id, id_len);
11290
11292 netbytes = htons(wt_len);
11294 mg_send(nc, opts.will_topic, wt_len);
11295
11296 netbytes = htons(wm_len);
11298 mg_send(nc, opts.will_message, wm_len);
11299 }
11300
11302 netbytes = htons(user_len);
11304 mg_send(nc, opts.user_name, user_len);
11305 }
11307 netbytes = htons(pw_len);
11309 mg_send(nc, opts.password, pw_len);
11310 }
11311
11312 if (pd != NULL) {
11313 pd->keep_alive = opts.keep_alive;
11314 }
11315}
11316
11318 uint16_t message_id,
int flags,
const void *
data,
11319 size_t len) {
11320 uint16_t netbytes;
11321 uint16_t topic_len = strlen(topic);
11322
11323 size_t total_len = 2 + topic_len + len;
11325 total_len += 2;
11326 }
11327
11329
11330 netbytes = htons(topic_len);
11332 mg_send(nc, topic, topic_len);
11333
11335 netbytes = htons(message_id);
11337 }
11338
11340}
11341
11344 size_t topics_len, uint16_t message_id) {
11345 uint16_t netbytes;
11347 uint16_t topic_len;
11348 size_t total_len = 2;
11349
11350 for (
i = 0;
i < topics_len;
i++) {
11351 total_len += 2 + strlen(topics[
i].topic) + 1;
11352 }
11353
11355
11356 netbytes = htons(message_id);
11357 mg_send(nc, (
char *) &netbytes, 2);
11358
11359 for (
i = 0;
i < topics_len;
i++) {
11360 topic_len = strlen(topics[
i].topic);
11361 netbytes = htons(topic_len);
11363 mg_send(nc, topics[
i].topic, topic_len);
11365 }
11366}
11367
11369 struct mg_str *topic, uint8_t *qos,
int pos) {
11370 unsigned char *buf = (
unsigned char *) msg->
payload.
p + pos;
11371 int new_pos;
11372
11373 if ((size_t) pos >= msg->payload.len) return -1;
11374
11375 topic->len = buf[0] << 8 | buf[1];
11376 topic->p = (char *) buf + 2;
11377 new_pos = pos + 2 + topic->
len + 1;
11378 if ((size_t) new_pos > msg->payload.len) return -1;
11379 *qos = buf[2 + topic->len];
11380 return new_pos;
11381}
11382
11384 size_t topics_len, uint16_t message_id) {
11385 uint16_t netbytes;
11387 uint16_t topic_len;
11388 size_t total_len = 2;
11389
11390 for (
i = 0;
i < topics_len;
i++) {
11391 total_len += 2 + strlen(topics[
i]);
11392 }
11393
11395
11396 netbytes = htons(message_id);
11397 mg_send(nc, (
char *) &netbytes, 2);
11398
11399 for (
i = 0;
i < topics_len;
i++) {
11400 topic_len = strlen(topics[
i]);
11401 netbytes = htons(topic_len);
11403 mg_send(nc, topics[
i], topic_len);
11404 }
11405}
11406
11408 uint8_t unused = 0;
11411 mg_send(nc, &return_code, 1);
11412}
11413
11414
11415
11416
11417
11418
11420 uint16_t message_id) {
11421 uint16_t netbytes;
11423
11424 mg_send_mqtt_header(nc, cmd, flags, 2 );
11425
11426 netbytes = htons(message_id);
11428}
11429
11432}
11433
11436}
11437
11440}
11441
11444}
11445
11447 uint16_t message_id) {
11449 uint16_t netbytes;
11450
11452
11453 netbytes = htons(message_id);
11455
11456 for (
i = 0;
i < qoss_len;
i++) {
11458 }
11459}
11460
11463}
11464
11467}
11468
11471}
11472
11475}
11476
11477#endif
11478#ifdef MG_MODULE_LINES
11479#line 1 "mongoose/src/mg_mqtt_server.c"
11480#endif
11481
11482
11483
11484
11485
11486
11487
11488
11489#if MG_ENABLE_MQTT_BROKER
11490
11491static void mg_mqtt_session_init(struct mg_mqtt_broker *brk,
11492 struct mg_mqtt_session *s,
11494 s->brk = brk;
11495 s->subscriptions = NULL;
11496 s->num_subscriptions = 0;
11497 s->nc = nc;
11498}
11499
11500static void mg_mqtt_add_session(struct mg_mqtt_session *s) {
11502}
11503
11504static void mg_mqtt_remove_session(struct mg_mqtt_session *s) {
11506}
11507
11508static void mg_mqtt_destroy_session(struct mg_mqtt_session *s) {
11510 for (
i = 0;
i < s->num_subscriptions;
i++) {
11511 MG_FREE((
void *) s->subscriptions[
i].topic);
11512 }
11515}
11516
11517static void mg_mqtt_close_session(struct mg_mqtt_session *s) {
11518 mg_mqtt_remove_session(s);
11519 mg_mqtt_destroy_session(s);
11520}
11521
11522void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data) {
11524 brk->user_data = user_data;
11525}
11526
11527static void mg_mqtt_broker_handle_connect(struct mg_mqtt_broker *brk,
11529 struct mg_mqtt_session *s =
11530 (
struct mg_mqtt_session *)
MG_CALLOC(1,
sizeof *s);
11531 if (s == NULL) {
11532
11534 return;
11535
11536 }
11537
11538
11539
11540 mg_mqtt_session_init(brk, s, nc);
11542 mg_mqtt_add_session(s);
11543
11545}
11546
11547static void mg_mqtt_broker_handle_subscribe(
struct mg_connection *nc,
11549 struct mg_mqtt_session *ss = (
struct mg_mqtt_session *) nc->
priv_2;
11550 uint8_t qoss[MG_MQTT_MAX_SESSION_SUBSCRIPTIONS];
11551 size_t num_subs = 0;
11553 uint8_t qos;
11554 int pos;
11556
11557 for (pos = 0;
11559 if (num_subs >= sizeof(MG_MQTT_MAX_SESSION_SUBSCRIPTIONS) ||
11560 (ss->num_subscriptions + num_subs >=
11561 MG_MQTT_MAX_SESSION_SUBSCRIPTIONS)) {
11563 return;
11564 }
11565 qoss[num_subs++] =
qos;
11566 }
11567
11568 if (num_subs > 0) {
11570 ss->subscriptions,
11571 sizeof(*ss->subscriptions) * (ss->num_subscriptions + num_subs));
11572 if (te == NULL) {
11574 return;
11575 }
11576 ss->subscriptions = te;
11577 for (pos = 0;
11578 pos < (int) msg->payload.len &&
11580 ss->num_subscriptions++) {
11581 te = &ss->subscriptions[ss->num_subscriptions];
11586 }
11587 }
11588
11589 if (pos == (int) msg->payload.len) {
11591 } else {
11592
11594 }
11595}
11596
11597static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk,
11599 struct mg_mqtt_session *s;
11601
11602 for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
11603 for (
i = 0;
i < s->num_subscriptions;
i++) {
11606 char buf[100], *p = buf;
11609 if (p == NULL) {
11610 return;
11611 }
11613 if (p != buf) {
11615 }
11616 break;
11617 }
11618 }
11619 }
11620}
11621
11624 struct mg_mqtt_broker *brk;
11625
11628 } else {
11629 brk = (
struct mg_mqtt_broker *) nc->
priv_2;
11630 }
11631
11632 switch (ev) {
11636 break;
11638 if (nc->
priv_2 == NULL) {
11639 mg_mqtt_broker_handle_connect(brk, nc);
11640 } else {
11641
11643 }
11644 break;
11646 if (nc->
priv_2 != NULL) {
11647 mg_mqtt_broker_handle_subscribe(nc, msg);
11648 } else {
11649
11651 }
11652 break;
11654 if (nc->
priv_2 != NULL) {
11655 mg_mqtt_broker_handle_publish(brk, msg);
11656 } else {
11657
11659 }
11660 break;
11663 mg_mqtt_close_session((
struct mg_mqtt_session *) nc->
priv_2);
11664 }
11665 break;
11666 }
11667}
11668
11669struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
11670 struct mg_mqtt_session *s) {
11672}
11673
11674#endif
11675#ifdef MG_MODULE_LINES
11676#line 1 "mongoose/src/mg_dns.c"
11677#endif
11678
11679
11680
11681
11682
11683#if MG_ENABLE_DNS
11684
11685
11686
11687
11689
11697};
11698
11703
11704 for (rr = (prev == NULL ? msg->
answers : prev + 1);
11706 if (rr->
rtype == query) {
11707 return rr;
11708 }
11709 }
11710 return NULL;
11711}
11712
11715 size_t data_len) {
11716 switch (rr->
rtype) {
11718 if (data_len < sizeof(struct in_addr)) {
11719 return -1;
11720 }
11722 return -1;
11723 }
11725 return 0;
11726#if MG_ENABLE_IPV6
11728 if (data_len < sizeof(struct in6_addr)) {
11729 return -1;
11730 }
11732 return 0;
11733#endif
11736 return 0;
11737 }
11738
11739 return -1;
11740}
11741
11745
11746 memset(&header, 0, sizeof(header));
11748 header.flags = htons(msg->
flags);
11751
11752 return mbuf_insert(io, pos, &header,
sizeof(header));
11753}
11754
11763}
11764
11766 const char *s;
11768 size_t pos = io->
len;
11769
11770 do {
11771 if ((s = strchr(
name,
'.')) == NULL) {
11773 }
11774
11775 if (s -
name > 127) {
11776 return -1;
11777 }
11781
11782 if (*s == '.') {
11784 }
11785
11788 } while (*s != '\0');
11790
11791 return io->
len - pos;
11792}
11793
11795 const char *
name,
size_t nlen,
const void *
rdata,
11796 size_t rlen) {
11797 size_t pos = io->
len;
11798 uint16_t u16;
11799 uint32_t u32;
11800
11802 return -1;
11803 }
11804
11806 return -1;
11807 }
11808
11809 u16 = htons(rr->
rtype);
11811 u16 = htons(rr->
rclass);
11813
11815 u32 = htonl(rr->
ttl);
11817
11819 int clen;
11820
11821 size_t off = io->
len;
11824 return -1;
11825 }
11826 u16 = clen;
11827 io->
buf[off] = u16 >> 8;
11828 io->
buf[off + 1] = u16 & 0xff;
11829 } else {
11830 u16 = htons((uint16_t) rlen);
11833 }
11834 }
11835
11836 return io->
len - pos;
11837}
11838
11840 int query_type) {
11845
11846 DBG((
"%s %d",
name, query_type));
11847
11849
11851 msg->
flags = 0x100;
11853
11855
11856 rr->
rtype = query_type;
11859
11861
11862 goto cleanup;
11863 }
11864
11865
11867 uint16_t len = htons((uint16_t) pkt.len);
11869 }
11870
11871 mg_send(nc, pkt.buf, pkt.len);
11873
11874cleanup:
11876}
11877
11880 int reply) {
11882 int chunk_len, data_len;
11883
11885 if (((
unsigned char *)
data)[0] & 0xc0) {
11887 break;
11888 }
11889 data += chunk_len + 1;
11890 }
11891
11893 return NULL;
11894 }
11895
11899
11902
11905
11907 if (reply) {
11909 return NULL;
11910 }
11911
11912 rr->
ttl = (uint32_t)
data[0] << 24 | (uint32_t)
data[1] << 16 |
11915
11916 data_len = *
data << 8 | *(
data + 1);
11918
11922 }
11924}
11925
11928 unsigned char *
data = (
unsigned char *) buf +
sizeof(*header);
11929 unsigned char *
end = (
unsigned char *) buf + len;
11931
11932 memset(msg, 0, sizeof(*msg));
11935
11936 if (len < (int) sizeof(*header)) return -1;
11937
11943 }
11947 }
11948
11951 if (
data == NULL)
return -1;
11952 }
11953
11956 if (
data == NULL)
return -1;
11957 }
11958
11959 return 0;
11960}
11961
11963 char *dst, int dst_len) {
11964 int chunk_len, num_ptrs = 0;
11965 char *old_dst = dst;
11966 const unsigned char *
data = (
unsigned char *)
name->p;
11967 const unsigned char *
end = (
unsigned char *) msg->
pkt.
p + msg->
pkt.
len;
11968
11970 return 0;
11971 }
11972
11973 while ((chunk_len = *
data++)) {
11974 int leeway = dst_len - (dst - old_dst);
11976 return 0;
11977 }
11978
11979 if ((chunk_len & 0xc0) == 0xc0) {
11980 uint16_t off = (
data[-1] & (~0xc0)) << 8 |
data[0];
11981 if (off >= msg->
pkt.
len) {
11982 return 0;
11983 }
11984
11985 if (++num_ptrs > 15) {
11986 return 0;
11987 }
11988 data = (
unsigned char *) msg->
pkt.
p + off;
11989 continue;
11990 }
11991 if (chunk_len > 63) {
11992 return 0;
11993 }
11994 if (chunk_len > leeway) {
11995 chunk_len = leeway;
11996 }
11997
11998 if (
data + chunk_len >=
end) {
11999 return 0;
12000 }
12001
12002 memcpy(dst,
data, chunk_len);
12004 dst += chunk_len;
12005 leeway -= chunk_len;
12006 if (leeway == 0) {
12007 return dst - old_dst;
12008 }
12009 *dst++ = '.';
12010 }
12011
12012 if (dst != old_dst) {
12013 *--dst = 0;
12014 }
12015 return dst - old_dst;
12016}
12017
12019 void *ev_data
MG_UD_ARG(
void *user_data)) {
12022
12023
12025
12026 switch (ev) {
12030 }
12032
12033 memset(&msg, 0, sizeof(msg));
12034 msg.
flags = 0x8081;
12037 uint16_t len = htons((uint16_t) io->
len);
12039 }
12041 } else {
12042
12044 }
12046 break;
12047 }
12048}
12049
12052}
12053
12054#endif
12055#ifdef MG_MODULE_LINES
12056#line 1 "mongoose/src/mg_dns_server.c"
12057#endif
12058
12059
12060
12061
12062
12063#if MG_ENABLE_DNS_SERVER
12064
12065
12066
12067
12068struct mg_dns_reply mg_dns_create_reply(struct
mbuf *io,
12070 struct mg_dns_reply rep;
12071 rep.msg = msg;
12072 rep.io = io;
12073 rep.start = io->len;
12074
12075
12076 msg->
flags |= 0x8080;
12078
12080 return rep;
12081}
12082
12083void mg_dns_send_reply(
struct mg_connection *nc,
struct mg_dns_reply *r) {
12084 size_t sent = r->io->len - r->start;
12087 uint16_t len = htons((uint16_t) sent);
12089 }
12090
12092 mg_send(nc, r->io->buf + r->start, r->io->len - r->start);
12093 r->io->len = r->start;
12094 }
12095}
12096
12097int mg_dns_reply_record(struct mg_dns_reply *reply,
12099 const char *
name,
int rtype,
int ttl,
const void *rdata,
12100 size_t rdata_len) {
12102 char rname[512];
12105 return -1;
12106 }
12107
12108 if (
name == NULL) {
12110 rname[511] = 0;
12112 }
12113
12114 *ans = *question;
12118
12120 rdata_len) == -1) {
12121 return -1;
12122 };
12123
12125 return 0;
12126}
12127
12128#endif
12129#ifdef MG_MODULE_LINES
12130#line 1 "mongoose/src/mg_resolv.c"
12131#endif
12132
12133
12134
12135
12136
12137#if MG_ENABLE_ASYNC_RESOLVER
12138
12139
12140
12141
12142#ifndef MG_DEFAULT_NAMESERVER
12143#define MG_DEFAULT_NAMESERVER "8.8.8.8"
12144#endif
12145
12154
12155
12158};
12159
12160
12161
12162
12163
12164
12166 int ret = -1;
12167
12168#ifdef _WIN32
12172 wchar_t subkey[512],
value[128],
12173 *
key = L
"SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces";
12174
12175 if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
key, 0, KEY_READ, &
hKey)) !=
12176 ERROR_SUCCESS) {
12177 fprintf(stderr,
"cannot open reg key %S: %ld\n",
key, err);
12178 ret = -1;
12179 } else {
12180 for (ret = -1,
i = 0; 1;
i++) {
12182 if (RegEnumKeyExW(
hKey,
i, subkey, &subkey_size, NULL, NULL, NULL,
12183 NULL) != ERROR_SUCCESS) {
12184 break;
12185 }
12186 if (RegOpenKeyExW(
hKey, subkey, 0, KEY_READ, &hSub) == ERROR_SUCCESS &&
12187 ((RegQueryValueExW(hSub, L
"NameServer", 0, &
type, (
void *)
value,
12188 &len) == ERROR_SUCCESS &&
12189 value[0] !=
'\0') ||
12190 (RegQueryValueExW(hSub, L
"DhcpNameServer", 0, &
type, (
void *)
value,
12191 &len) == ERROR_SUCCESS &&
12192 value[0] !=
'\0'))) {
12193
12194
12195
12196
12197
12198
12199
12201 if (
comma != NULL) {
12203 }
12204
12206 ret = 0;
12207 RegCloseKey(hSub);
12208 break;
12209 }
12210 }
12212 }
12213#elif MG_ENABLE_FILESYSTEM && defined(MG_RESOLV_CONF_FILE_NAME)
12215 char line[512];
12216
12217 if ((
fp =
mg_fopen(MG_RESOLV_CONF_FILE_NAME,
"r")) == NULL) {
12218 ret = -1;
12219 } else {
12220
12221 for (ret = -1; fgets(line,
sizeof(line),
fp) != NULL;) {
12222 unsigned int a, b,
c,
d;
12223 if (sscanf(line,
"nameserver %u.%u.%u.%u", &a, &b, &
c, &
d) == 4) {
12224 snprintf(
name, name_len,
"%u.%u.%u.%u", a, b,
c,
d);
12225 ret = 0;
12226 break;
12227 }
12228 }
12230 }
12231#else
12233#endif
12234
12235 return ret;
12236}
12237
12239#if MG_ENABLE_FILESYSTEM && defined(MG_HOSTS_FILE_NAME)
12240
12242 char line[1024];
12243 char *p;
12244 char alias[256];
12245 unsigned int a, b,
c,
d;
12246 int len = 0;
12247
12248 if ((
fp =
mg_fopen(MG_HOSTS_FILE_NAME,
"r")) == NULL) {
12249 return -1;
12250 }
12251
12252 for (; fgets(line,
sizeof(line),
fp) != NULL;) {
12253 if (line[0] == '#') continue;
12254
12255 if (sscanf(line,
"%u.%u.%u.%u%n", &a, &b, &
c, &
d, &len) == 0) {
12256
12257 continue;
12258 }
12259 for (p = line + len; sscanf(p, "%s%n", alias, &len) == 1; p += len) {
12260 if (strcmp(alias,
name) == 0) {
12261 usa->
sin.sin_addr.s_addr = htonl(a << 24 | b << 16 |
c << 8 |
d);
12263 return 0;
12264 }
12265 }
12266 }
12267
12269#else
12272#endif
12273
12274 return -1;
12275}
12276
12279 time_t now = (time_t)
mg_time();
12282#if !MG_ENABLE_CALLBACK_USERDATA
12284#endif
12285
12287 DBG((
"ev=%d user_data=%p", ev, user_data));
12288 }
12289
12291
12292 if (req == NULL) {
12293 return;
12294 }
12295
12296 switch (ev) {
12301 break;
12302 }
12304
12310 }
12311 break;
12319 } else {
12321 }
12324 break;
12326
12327
12328
12329
12330 nc->
flags &= ~MG_F_CLOSE_IMMEDIATELY;
12332 break;
12336 break;
12338
12339 if (req != NULL) {
12342#ifdef MG_LOG_DNS_FAILURES
12344#endif
12348 }
12349 break;
12350 }
12351}
12352
12356 memset(&opts, 0, sizeof(opts));
12358}
12359
12366 char dns_server_buff[17], nameserver_url[26];
12367
12368 if (nameserver == NULL) {
12370 }
12371
12373
12374
12376 if (req == NULL) {
12377 return -1;
12378 }
12379
12381 req->
name[
sizeof(req->
name) - 1] =
'\0';
12382
12386
12389
12390
12391 if (nameserver == NULL) {
12393 sizeof(dns_server_buff)) != -1) {
12394 nameserver = dns_server_buff;
12395 } else {
12397 }
12398 }
12399
12400 snprintf(nameserver_url, sizeof(nameserver_url), "udp://%s:53", nameserver);
12401
12403 if (dns_nc == NULL) {
12405 return -1;
12406 }
12410 }
12411
12412 return 0;
12413}
12414
12418 if (nameserver != NULL) {
12420 }
12421}
12422
12423#endif
12424#ifdef MG_MODULE_LINES
12425#line 1 "mongoose/src/mg_coap.c"
12426#endif
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447#if MG_ENABLE_COAP
12448
12449void mg_coap_free_options(struct mg_coap_message *cm) {
12450 while (cm->options != NULL) {
12451 struct mg_coap_option *next = cm->options->next;
12453 cm->options = next;
12454 }
12455}
12456
12457struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
12458 uint32_t number,
char *
value,
12459 size_t len) {
12460 struct mg_coap_option *new_option =
12461 (
struct mg_coap_option *)
MG_CALLOC(1,
sizeof(*new_option));
12462
12463 new_option->number = number;
12464 new_option->value.p =
value;
12465 new_option->value.len = len;
12466
12467 if (cm->options == NULL) {
12468 cm->options = cm->optiomg_tail = new_option;
12469 } else {
12470
12471
12472
12473
12474
12475 if (cm->optiomg_tail->number <= new_option->number) {
12476
12477 cm->optiomg_tail = cm->optiomg_tail->next = new_option;
12478 } else {
12479
12480 struct mg_coap_option *current_opt = cm->options;
12481 struct mg_coap_option *prev_opt = 0;
12482
12483 while (current_opt != NULL) {
12484 if (current_opt->number > new_option->number) {
12485 break;
12486 }
12487 prev_opt = current_opt;
12488 current_opt = current_opt->next;
12489 }
12490
12491 if (prev_opt != NULL) {
12492 prev_opt->next = new_option;
12493 new_option->next = current_opt;
12494 } else {
12495
12496 new_option->next = cm->options;
12497 cm->options = new_option;
12498 }
12499 }
12500 }
12501
12502 return new_option;
12503}
12504
12505
12506
12507
12508
12509
12510static char *coap_parse_header(
char *ptr,
struct mbuf *io,
12511 struct mg_coap_message *cm) {
12512 if (io->
len <
sizeof(uint32_t)) {
12513 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12514 return NULL;
12515 }
12516
12517
12518
12519
12520
12521
12522
12523 if (((uint8_t) *ptr >> 6) != 1) {
12524 cm->flags |= MG_COAP_IGNORE;
12525 return NULL;
12526 }
12527
12528
12529
12530
12531
12532
12533 cm->msg_type = ((uint8_t) *ptr & 0x30) >> 4;
12534 cm->flags |= MG_COAP_MSG_TYPE_FIELD;
12535
12536
12537
12538
12539
12540
12541
12542 cm->token.len = *ptr & 0x0F;
12543 if (cm->token.len > 8) {
12544 cm->flags |= MG_COAP_FORMAT_ERROR;
12545 return NULL;
12546 }
12547
12548 ptr++;
12549
12550
12551
12552
12553
12554 cm->code_class = (uint8_t) *ptr >> 5;
12555 cm->code_detail = *ptr & 0x1F;
12556 cm->flags |= (MG_COAP_CODE_CLASS_FIELD | MG_COAP_CODE_DETAIL_FIELD);
12557
12558 ptr++;
12559
12560
12561 cm->msg_id = (uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1);
12562 cm->flags |= MG_COAP_MSG_ID_FIELD;
12563
12564 ptr += 2;
12565
12566 return ptr;
12567}
12568
12569
12570
12571
12572
12573
12574static char *coap_get_token(
char *ptr,
struct mbuf *io,
12575 struct mg_coap_message *cm) {
12576 if (cm->token.len != 0) {
12577 if (ptr + cm->token.len > io->
buf + io->
len) {
12578 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12579 return NULL;
12580 } else {
12581 cm->token.p = ptr;
12582 ptr += cm->token.len;
12583 cm->flags |= MG_COAP_TOKEN_FIELD;
12584 }
12585 }
12586
12587 return ptr;
12588}
12589
12590
12591
12592
12593
12594
12595static int coap_get_ext_opt(
char *ptr,
struct mbuf *io, uint16_t *opt_info) {
12596 int ret = 0;
12597
12598 if (*opt_info == 13) {
12599
12600
12601
12602
12603 if (ptr < io->buf + io->
len) {
12604 *opt_info = (uint8_t) *ptr + 13;
12605 ret = sizeof(uint8_t);
12606 } else {
12607 ret = -1;
12608 }
12609 } else if (*opt_info == 14) {
12610
12611
12612
12613
12614 if (ptr +
sizeof(uint8_t) < io->
buf + io->
len) {
12615 *opt_info = ((uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1)) + 269;
12616 ret = sizeof(uint16_t);
12617 } else {
12618 ret = -1;
12619 }
12620 }
12621
12622 return ret;
12623}
12624
12625
12626
12627
12628
12629
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639
12640
12641static char *coap_get_options(
char *ptr,
struct mbuf *io,
12642 struct mg_coap_message *cm) {
12643 uint16_t prev_opt = 0;
12644
12645 if (ptr == io->
buf + io->
len) {
12646
12647 return NULL;
12648 }
12649
12650
12651 while (ptr < io->buf + io->
len && (uint8_t) *ptr != 0xFF) {
12652 uint16_t option_delta, option_lenght;
12653 int optinfo_len;
12654
12655
12656 option_delta = ((uint8_t) *ptr & 0xF0) >> 4;
12657
12658 option_lenght = *ptr & 0x0F;
12659
12660 if (option_delta == 15 || option_lenght == 15) {
12661
12662
12663
12664
12665 cm->flags |= MG_COAP_FORMAT_ERROR;
12666 break;
12667 }
12668
12669 ptr++;
12670
12671
12672 optinfo_len = coap_get_ext_opt(ptr, io, &option_delta);
12673 if (optinfo_len == -1) {
12674 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12675 break;
12676 }
12677
12678 ptr += optinfo_len;
12679
12680
12681 optinfo_len = coap_get_ext_opt(ptr, io, &option_lenght);
12682 if (optinfo_len == -1) {
12683 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12684 break;
12685 }
12686
12687 ptr += optinfo_len;
12688
12689
12690
12691
12692
12693
12694 option_delta += prev_opt;
12695
12696 mg_coap_add_option(cm, option_delta, ptr, option_lenght);
12697
12698 prev_opt = option_delta;
12699
12700 if (ptr + option_lenght > io->
buf + io->
len) {
12701 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12702 break;
12703 }
12704
12705 ptr += option_lenght;
12706 }
12707
12708 if ((cm->flags & MG_COAP_ERROR) != 0) {
12709 mg_coap_free_options(cm);
12710 return NULL;
12711 }
12712
12713 cm->flags |= MG_COAP_OPTIOMG_FIELD;
12714
12715 if (ptr == io->
buf + io->
len) {
12716
12717 return NULL;
12718 }
12719
12720 ptr++;
12721
12722 return ptr;
12723}
12724
12725uint32_t mg_coap_parse(
struct mbuf *io,
struct mg_coap_message *cm) {
12726 char *ptr;
12727
12728 memset(cm, 0, sizeof(*cm));
12729
12730 if ((ptr = coap_parse_header(io->
buf, io, cm)) == NULL) {
12731 return cm->flags;
12732 }
12733
12734 if ((ptr = coap_get_token(ptr, io, cm)) == NULL) {
12735 return cm->flags;
12736 }
12737
12738 if ((ptr = coap_get_options(ptr, io, cm)) == NULL) {
12739 return cm->flags;
12740 }
12741
12742
12743 cm->payload.len = io->
len - (ptr - io->
buf);
12744 if (cm->payload.len != 0) {
12745 cm->payload.p = ptr;
12746 cm->flags |= MG_COAP_PAYLOAD_FIELD;
12747 }
12748
12749 return cm->flags;
12750}
12751
12752
12753
12754
12755
12756
12757static size_t coap_get_ext_opt_size(uint32_t
value) {
12758 int ret = 0;
12759
12761 ret = sizeof(uint8_t);
12762 }
else if (
value > 0xFF + 13 &&
value <= 0xFFFF + 269) {
12763 ret = sizeof(uint16_t);
12764 }
12765
12766 return ret;
12767}
12768
12769
12770
12771
12772
12773
12774static int coap_split_opt(uint32_t
value, uint8_t *
base, uint16_t *ext) {
12775 int ret = 0;
12776
12779 }
else if (
value >= 13 &&
value <= 0xFF + 13) {
12782 ret = sizeof(uint8_t);
12783 }
else if (
value > 0xFF + 13 &&
value <= 0xFFFF + 269) {
12785 *ext =
value - 269;
12786 ret = sizeof(uint16_t);
12787 }
12788
12789 return ret;
12790}
12791
12792
12793
12794
12795
12796
12797static char *coap_add_uint16(char *ptr, uint16_t val) {
12798 *ptr = val >> 8;
12799 ptr++;
12800 *ptr = val & 0x00FF;
12801 ptr++;
12802 return ptr;
12803}
12804
12805
12806
12807
12808
12809
12810static char *coap_add_opt_info(char *ptr, uint16_t val, size_t len) {
12811 if (len == sizeof(uint8_t)) {
12812 *ptr = (char) val;
12813 ptr++;
12814 } else if (len == sizeof(uint16_t)) {
12815 ptr = coap_add_uint16(ptr, val);
12816 }
12817
12818 return ptr;
12819}
12820
12821
12822
12823
12824
12825
12826static uint32_t coap_calculate_packet_size(struct mg_coap_message *cm,
12827 size_t *len) {
12828 struct mg_coap_option *opt;
12829 uint32_t prev_opt_number;
12830
12831 *len = 4;
12832 if (cm->msg_type > MG_COAP_MSG_MAX) {
12833 return MG_COAP_ERROR | MG_COAP_MSG_TYPE_FIELD;
12834 }
12835 if (cm->token.len > 8) {
12836 return MG_COAP_ERROR | MG_COAP_TOKEN_FIELD;
12837 }
12838 if (cm->code_class > 7) {
12839 return MG_COAP_ERROR | MG_COAP_CODE_CLASS_FIELD;
12840 }
12841 if (cm->code_detail > 31) {
12842 return MG_COAP_ERROR | MG_COAP_CODE_DETAIL_FIELD;
12843 }
12844
12845 *len += cm->token.len;
12846 if (cm->payload.len != 0) {
12847 *len += cm->payload.len + 1;
12848 }
12849
12850 opt = cm->options;
12851 prev_opt_number = 0;
12852 while (opt != NULL) {
12853 *len += 1;
12854 *len += coap_get_ext_opt_size(opt->number - prev_opt_number);
12855 *len += coap_get_ext_opt_size((uint32_t) opt->value.len);
12856
12857
12858
12859
12860
12861
12862 if ((opt->next != NULL && opt->number > opt->next->number) ||
12863 opt->value.len > 0xFFFF + 269 ||
12864 opt->number - prev_opt_number > 0xFFFF + 269) {
12865 return MG_COAP_ERROR | MG_COAP_OPTIOMG_FIELD;
12866 }
12867 *len += opt->value.len;
12868 prev_opt_number = opt->number;
12869 opt = opt->next;
12870 }
12871
12872 return 0;
12873}
12874
12875uint32_t mg_coap_compose(
struct mg_coap_message *cm,
struct mbuf *io) {
12876 struct mg_coap_option *opt;
12877 uint32_t res, prev_opt_number;
12878 size_t prev_io_len, packet_size;
12879 char *ptr;
12880
12881 res = coap_calculate_packet_size(cm, &packet_size);
12882 if (res != 0) {
12883 return res;
12884 }
12885
12886
12887 prev_io_len = io->
len;
12888 if (
mbuf_append(io, NULL, packet_size) == 0)
return MG_COAP_ERROR;
12889 ptr = io->
buf + prev_io_len;
12890
12891
12892
12893
12894
12895
12896
12897 *ptr = (1 << 6) | (cm->msg_type << 4) | (uint8_t)(cm->token.len);
12898 ptr++;
12899
12900
12901 *ptr = (cm->code_class << 5) | (cm->code_detail);
12902 ptr++;
12903
12904 ptr = coap_add_uint16(ptr, cm->msg_id);
12905
12906 if (cm->token.len != 0) {
12907 memcpy(ptr, cm->token.p, cm->token.len);
12908 ptr += cm->token.len;
12909 }
12910
12911 opt = cm->options;
12912 prev_opt_number = 0;
12913 while (opt != NULL) {
12914 uint8_t delta_base = 0, length_base = 0;
12915 uint16_t delta_ext = 0, length_ext = 0;
12916
12917 size_t opt_delta_len =
12918 coap_split_opt(opt->number - prev_opt_number, &delta_base, &delta_ext);
12919 size_t opt_lenght_len =
12920 coap_split_opt((uint32_t) opt->value.len, &length_base, &length_ext);
12921
12922 *ptr = (delta_base << 4) | length_base;
12923 ptr++;
12924
12925 ptr = coap_add_opt_info(ptr, delta_ext, opt_delta_len);
12926 ptr = coap_add_opt_info(ptr, length_ext, opt_lenght_len);
12927
12928 if (opt->value.len != 0) {
12929 memcpy(ptr, opt->value.p, opt->value.len);
12930 ptr += opt->value.len;
12931 }
12932
12933 prev_opt_number = opt->number;
12934 opt = opt->next;
12935 }
12936
12937 if (cm->payload.len != 0) {
12938 *ptr = (char) -1;
12939 ptr++;
12940 memcpy(ptr, cm->payload.p, cm->payload.len);
12941 }
12942
12943 return 0;
12944}
12945
12947 struct mg_coap_message *cm) {
12948 struct mbuf packet_out;
12949 uint32_t compose_res;
12950
12952 compose_res = mg_coap_compose(cm, &packet_out);
12953 if (compose_res != 0) {
12954 return compose_res;
12955 }
12956
12957 mg_send(nc, packet_out.buf, (
int) packet_out.len);
12959
12960 return 0;
12961}
12962
12963uint32_t mg_coap_send_ack(
struct mg_connection *nc, uint16_t msg_id) {
12964 struct mg_coap_message cm;
12965 memset(&cm, 0, sizeof(cm));
12966 cm.msg_type = MG_COAP_MSG_ACK;
12967 cm.msg_id = msg_id;
12968
12969 return mg_coap_send_message(nc, &cm);
12970}
12971
12973 void *ev_data
MG_UD_ARG(
void *user_data)) {
12975 struct mg_coap_message cm;
12976 uint32_t parse_res;
12977
12978 memset(&cm, 0, sizeof(cm));
12979
12981
12982 switch (ev) {
12984 parse_res = mg_coap_parse(io, &cm);
12985 if ((parse_res & MG_COAP_IGNORE) == 0) {
12986 if ((cm.flags & MG_COAP_NOT_ENOUGH_DATA) != 0) {
12987
12988
12989
12990
12991 cm.flags |= MG_COAP_FORMAT_ERROR;
12992 }
12993 nc->
handler(nc, MG_COAP_EVENT_BASE + cm.msg_type,
12995 }
12996
12997 mg_coap_free_options(&cm);
12999 break;
13000 }
13001}
13002
13003
13004
13005
13006
13007
13008
13009
13010
13011
13013
13015 return -1;
13016 }
13017
13019
13020 return 0;
13021}
13022
13023#endif
13024#ifdef MG_MODULE_LINES
13025#line 1 "mongoose/src/mg_sntp.c"
13026#endif
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036#if MG_ENABLE_SNTP
13037
13038#define SNTP_TIME_OFFSET 2208988800
13039
13040#ifndef SNTP_TIMEOUT
13041#define SNTP_TIMEOUT 10
13042#endif
13043
13044#ifndef SNTP_ATTEMPTS
13045#define SNTP_ATTEMPTS 3
13046#endif
13047
13048static uint64_t mg_get_sec(uint64_t val) {
13049 return (val & 0xFFFFFFFF00000000) >> 32;
13050}
13051
13052static uint64_t mg_get_usec(uint64_t val) {
13053 uint64_t tmp = (val & 0x00000000FFFFFFFF);
13054 tmp *= 1000000;
13055 tmp >>= 32;
13056 return tmp;
13057}
13058
13059static void mg_ntp_to_tv(uint64_t val,
struct timeval *
tv) {
13060 uint64_t tmp;
13061 tmp = mg_get_sec(val);
13062 tmp -= SNTP_TIME_OFFSET;
13064 tv->tv_usec = mg_get_usec(val);
13065}
13066
13067static void mg_get_ntp_ts(const char *ntp, uint64_t *val) {
13068 uint32_t tmp;
13069 memcpy(&tmp, ntp, sizeof(tmp));
13070 tmp = ntohl(tmp);
13071 *val = (uint64_t) tmp << 32;
13072 memcpy(&tmp, ntp + 4, sizeof(tmp));
13073 tmp = ntohl(tmp);
13074 *val |= tmp;
13075}
13076
13078 uint8_t buf[48] = {0};
13079
13080
13081
13082
13083
13084 buf[0] = (3 << 6) | (4 << 3) | 3;
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106#ifndef MG_SNTP_NO_DELAY_CORRECTION
13107 uint32_t sec;
13108 sec = htonl((uint32_t)(
mg_time() + SNTP_TIME_OFFSET));
13109 memcpy(&buf[40], &sec, sizeof(sec));
13110#endif
13111
13113}
13114
13115#ifndef MG_SNTP_NO_DELAY_CORRECTION
13116static uint64_t mg_calculate_delay(uint64_t t1, uint64_t t2, uint64_t t3) {
13117
13118 uint64_t d1 = ((
mg_time() + SNTP_TIME_OFFSET) * 1000000) -
13119 (mg_get_sec(t1) * 1000000 + mg_get_usec(t1));
13120 uint64_t d2 = (mg_get_sec(t3) * 1000000 + mg_get_usec(t3)) -
13121 (mg_get_sec(t2) * 1000000 + mg_get_usec(t2));
13122
13123 return (d1 > d2) ? d1 - d2 : 0;
13124}
13125#endif
13126
13127MG_INTERNAL int mg_sntp_parse_reply(
const char *buf,
int len,
13128 struct mg_sntp_message *msg) {
13129 uint8_t hdr;
13130 uint64_t trsm_ts_T3, delay = 0;
13131 int mode;
13133
13134 if (len < 48) {
13135 return -1;
13136 }
13137
13138 hdr = buf[0];
13139
13140 if ((hdr & 0x38) >> 3 != 4) {
13141
13142 return -1;
13143 }
13144
13145 mode = hdr & 0x7;
13146 if (mode != 4 && mode != 5) {
13147
13148 return -1;
13149 }
13150
13151 memset(msg, 0, sizeof(*msg));
13152
13153 msg->kiss_of_death = (buf[1] == 0);
13154
13155 mg_get_ntp_ts(&buf[40], &trsm_ts_T3);
13156
13157#ifndef MG_SNTP_NO_DELAY_CORRECTION
13158 {
13159 uint64_t orig_ts_T1, recv_ts_T2;
13160 mg_get_ntp_ts(&buf[24], &orig_ts_T1);
13161 mg_get_ntp_ts(&buf[32], &recv_ts_T2);
13162 delay = mg_calculate_delay(orig_ts_T1, recv_ts_T2, trsm_ts_T3);
13163 }
13164#endif
13165
13166 mg_ntp_to_tv(trsm_ts_T3, &
tv);
13167
13168 msg->time = (double)
tv.tv_sec + (((
double)
tv.tv_usec + delay) / 1000000.0);
13169
13170 return 0;
13171}
13172
13174 void *ev_data
MG_UD_ARG(
void *user_data)) {
13175 struct mbuf *io = &
c->recv_mbuf;
13176 struct mg_sntp_message msg;
13177
13179
13180 switch (ev) {
13182 if (mg_sntp_parse_reply(io->
buf, io->
len, &msg) < 0) {
13183 DBG((
"Invalid SNTP packet received (%d)", (
int) io->
len));
13184 c->handler(
c, MG_SNTP_MALFORMED_REPLY, NULL
MG_UD_ARG(user_data));
13185 } else {
13186 c->handler(
c, MG_SNTP_REPLY, (
void *) &msg
MG_UD_ARG(user_data));
13187 }
13188
13190 break;
13191 }
13192 }
13193}
13194
13197 return -1;
13198 }
13199
13200 c->proto_handler = mg_sntp_handler;
13201
13202 return 0;
13203}
13204
13208 const char *sntp_server_name) {
13210 char url[100], *p_url = url;
13211 const char *proto = "", *port = "", *tmp;
13212
13213
13214 tmp = strchr(sntp_server_name, ':');
13215 if (tmp != NULL && *(tmp + 1) == '/') {
13216 tmp = strchr(tmp + 1, ':');
13217 }
13218
13219 if (tmp == NULL) {
13220 port = ":123";
13221 }
13222
13223
13224 if (strncmp(sntp_server_name, "udp://", 6) != 0) {
13225 proto = "udp://";
13226 }
13227
13228 mg_asprintf(&p_url,
sizeof(url),
"%s%s%s", proto, sntp_server_name, port);
13229
13231
13233 goto cleanup;
13234 }
13235
13236 mg_set_protocol_sntp(
c);
13237
13238cleanup:
13239 if (p_url != url) {
13241 }
13242
13244}
13245
13246struct sntp_data {
13249};
13250
13251static void mg_sntp_util_ev_handler(
struct mg_connection *
c,
int ev,
13252 void *ev_data
MG_UD_ARG(
void *user_data)) {
13253#if !MG_ENABLE_CALLBACK_USERDATA
13254 void *user_data =
c->user_data;
13255#endif
13256 struct sntp_data *sd = (struct sntp_data *) user_data;
13257
13258 switch (ev) {
13260 if (*(int *) ev_data != 0) {
13261 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_FAILED, NULL);
13262 break;
13263 }
13264
13266 if (sd->count <= SNTP_ATTEMPTS) {
13267 mg_sntp_send_request(
c);
13269 sd->count++;
13270 } else {
13271 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_FAILED, NULL);
13273 }
13274 break;
13275 case MG_SNTP_MALFORMED_REPLY:
13276 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_FAILED, NULL);
13278 break;
13279 case MG_SNTP_REPLY:
13280 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_REPLY, ev_data);
13282 break;
13285 c->user_data = NULL;
13286 break;
13287 }
13288}
13289
13292 const char *sntp_server_name) {
13294 struct sntp_data *sd = (
struct sntp_data *)
MG_CALLOC(1,
sizeof(*sd));
13295 if (sd == NULL) {
13296 return NULL;
13297 }
13298
13299 c = mg_sntp_connect(mgr,
MG_CB(mg_sntp_util_ev_handler, sd),
13300 sntp_server_name);
13303 return NULL;
13304 }
13305
13306 sd->hander = event_handler;
13307#if !MG_ENABLE_CALLBACK_USERDATA
13309#endif
13310
13312}
13313
13314#endif
13315#ifdef MG_MODULE_LINES
13316#line 1 "mongoose/src/mg_socks.c"
13317#endif
13318
13319
13320
13321
13322
13323#if MG_ENABLE_SOCKS
13324
13325
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336
13338 struct mbuf *r = &
c->recv_mbuf;
13339 if (r->
buf[0] != MG_SOCKS_VERSION) {
13341 }
else if (r->
len > 2 && (
size_t) r->
buf[1] + 2 <= r->
len) {
13342
13343 unsigned char reply[2] = {MG_SOCKS_VERSION, MG_SOCKS_HANDSHAKE_FAILURE};
13345 for (
i = 2;
i < r->
buf[1] + 2;
i++) {
13346
13347 if (r->
buf[
i] == MG_SOCKS_HANDSHAKE_NOAUTH) reply[1] = r->
buf[
i];
13348 }
13351 c->flags |= MG_SOCKS_HANDSHAKE_DONE;
13352 }
13353}
13354
13357 if (c2 != NULL) {
13359 c2->user_data = NULL;
13360 }
13362 c->user_data = NULL;
13363}
13364
13367 if (c2 != NULL) {
13368 mg_send(c2,
c->recv_mbuf.buf,
c->recv_mbuf.len);
13370 } else {
13372 }
13373}
13374
13375static void serv_ev_handler(
struct mg_connection *
c,
int ev,
void *ev_data) {
13381 int res = *(int *) ev_data;
13382 if (res != 0)
LOG(
LL_ERROR, (
"connect error: %d", res));
13383 }
13384}
13385
13389 c->user_data = serv;
13390}
13391
13392
13393
13394
13395
13396
13397
13398
13399
13400
13402 struct mbuf *r = &
c->recv_mbuf;
13403 unsigned char *p = (
unsigned char *) r->
buf;
13404 unsigned char addr_len = 4, reply = MG_SOCKS_SUCCESS;
13405 int ver, cmd, atyp;
13407
13408 if (r->
len < 8)
return;
13409 ver = p[0];
13410 cmd = p[1];
13411 atyp = p[3];
13412
13413
13414 if (ver != MG_SOCKS_VERSION || cmd != MG_SOCKS_CMD_CONNECT) {
13415 reply = MG_SOCKS_CMD_NOT_SUPPORTED;
13416 } else if (atyp == MG_SOCKS_ADDR_IPV4) {
13417 addr_len = 4;
13418 if (r->
len < (
size_t) addr_len + 6)
return;
13419 snprintf(
addr,
sizeof(
addr),
"%d.%d.%d.%d:%d", p[4], p[5], p[6], p[7],
13420 p[8] << 8 | p[9]);
13421 mg_socks5_connect(
c,
addr);
13422 } else if (atyp == MG_SOCKS_ADDR_IPV6) {
13423 addr_len = 16;
13424 if (r->
len < (
size_t) addr_len + 6)
return;
13425 snprintf(
addr,
sizeof(
addr),
"[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
13426 p[4] << 8 | p[5], p[6] << 8 | p[7], p[8] << 8 | p[9],
13427 p[10] << 8 | p[11], p[12] << 8 | p[13], p[14] << 8 | p[15],
13428 p[16] << 8 | p[17], p[18] << 8 | p[19], p[20] << 8 | p[21]);
13429 mg_socks5_connect(
c,
addr);
13430 } else if (atyp == MG_SOCKS_ADDR_DOMAIN) {
13431 addr_len = p[4] + 1;
13432 if (r->
len < (
size_t) addr_len + 6)
return;
13433 snprintf(
addr,
sizeof(
addr),
"%.*s:%d", p[4], p + 5,
13434 p[4 + addr_len] << 8 | p[4 + addr_len + 1]);
13435 mg_socks5_connect(
c,
addr);
13436 } else {
13437 reply = MG_SOCKS_ADDR_NOT_SUPPORTED;
13438 }
13439
13440
13441
13442
13443
13444
13445
13446
13447
13448
13449 {
13450 unsigned char buf[] = {MG_SOCKS_VERSION, reply, 0};
13452 }
13454
13456 c->flags |= MG_SOCKS_CONNECT_DONE;
13457}
13458
13459static void socks_handler(
struct mg_connection *
c,
int ev,
void *ev_data) {
13461 if (!(
c->flags & MG_SOCKS_HANDSHAKE_DONE)) mg_socks5_handshake(
c);
13462 if (
c->flags & MG_SOCKS_HANDSHAKE_DONE &&
13463 !(
c->flags & MG_SOCKS_CONNECT_DONE)) {
13464 mg_socks5_handle_request(
c);
13465 }
13466 if (
c->flags & MG_SOCKS_CONNECT_DONE) relay_data(
c);
13469 }
13470 (void) ev_data;
13471}
13472
13474 c->proto_handler = socks_handler;
13475}
13476#endif
13477#ifdef MG_MODULE_LINES
13478#line 1 "common/platforms/cc3200/cc3200_libc.c"
13479#endif
13480
13481
13482
13483
13484
13485
13486
13487
13488
13489
13490
13491
13492
13493
13494
13495
13496
13497#if CS_PLATFORM == CS_P_CC3200
13498
13499
13500#include <stdio.h>
13501#include <string.h>
13502
13503#ifndef __TI_COMPILER_VERSION__
13504#include <reent.h>
13505#include <sys/stat.h>
13506#include <sys/time.h>
13507#include <unistd.h>
13508#endif
13509
13510#include <inc/hw_types.h>
13511#include <inc/hw_memmap.h>
13512#include <driverlib/prcm.h>
13513#include <driverlib/rom.h>
13514#include <driverlib/rom_map.h>
13515#include <driverlib/uart.h>
13516#include <driverlib/utils.h>
13517
13518#define CONSOLE_UART UARTA0_BASE
13519
13520#ifdef __TI_COMPILER_VERSION__
13521int asprintf(char **strp, const char *fmt, ...) {
13522 va_list ap;
13524
13526 if (*strp == NULL) return -1;
13527
13528 va_start(ap, fmt);
13529 len = vsnprintf(*strp, BUFSIZ, fmt, ap);
13530 va_end(ap);
13531
13534 if (*strp == NULL) return -1;
13535 }
13536
13537 if (
len >= BUFSIZ) {
13538 va_start(ap, fmt);
13539 len = vsnprintf(*strp,
len + 1, fmt, ap);
13540 va_end(ap);
13541 }
13542
13544}
13545
13546#if MG_TI_NO_HOST_INTERFACE
13547time_t HOSTtime() {
13548 struct timeval tp;
13550 return tp.tv_sec;
13551}
13552#endif
13553
13554#endif
13555
13557 while (*
str !=
'\0') {
13560 }
13561}
13562
13565
13567 while (1)
13568 ;
13569}
13570
13573 fprint_str(stderr,
" is not implemented\n");
13575}
13576
13577int _kill(
int pid,
int sig) {
13578 (void) pid;
13579 (void) sig;
13581 return -1;
13582}
13583
13585 fprint_str(stderr,
"_getpid is not implemented\n");
13586 return 42;
13587}
13588
13590
13591 return fd < 2;
13592}
13593
13594#endif
13595#ifdef MG_MODULE_LINES
13596#line 1 "common/platforms/msp432/msp432_libc.c"
13597#endif
13598
13599
13600
13601
13602
13603
13604
13605
13606
13607
13608
13609
13610
13611
13612
13613
13614
13615#if CS_PLATFORM == CS_P_MSP432
13616
13617#include <ti/sysbios/BIOS.h>
13618#include <ti/sysbios/knl/Clock.h>
13619
13621 uint32_t ticks = Clock_getTicks();
13622 tp->tv_sec = ticks / 1000;
13623 tp->tv_usec = (ticks % 1000) * 1000;
13624 return 0;
13625}
13626
13627#endif
13628#ifdef MG_MODULE_LINES
13629#line 1 "common/platforms/nrf5/nrf5_libc.c"
13630#endif
13631
13632
13633
13634
13635
13636
13637
13638
13639
13640
13641
13642
13643
13644
13645
13646
13647
13648#if (CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52) && \
13649 defined(__ARMCC_VERSION)
13651
13652 tp->tv_sec = 0;
13653 tp->tv_usec = 0;
13654 return 0;
13655}
13656#endif
13657#ifdef MG_MODULE_LINES
13658#line 1 "common/platforms/simplelink/sl_fs_slfs.h"
13659#endif
13660
13661
13662
13663
13664
13665
13666
13667
13668
13669
13670
13671
13672
13673
13674
13675
13676
13677#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
13678#define CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
13679
13680#if defined(MG_FS_SLFS)
13681
13682#include <stdio.h>
13683#ifndef __TI_COMPILER_VERSION__
13684#include <unistd.h>
13685#include <sys/stat.h>
13686#endif
13687
13688#define MAX_OPEN_SLFS_FILES 8
13689
13690
13691int fs_slfs_open(const char *pathname, int flags, mode_t mode);
13692int fs_slfs_close(int fd);
13693ssize_t fs_slfs_read(
int fd,
void *buf,
size_t count);
13694ssize_t fs_slfs_write(
int fd,
const void *buf,
size_t count);
13695int fs_slfs_stat(const char *pathname, struct stat *s);
13696int fs_slfs_fstat(int fd, struct stat *s);
13697off_t fs_slfs_lseek(
int fd, off_t
offset,
int whence);
13698int fs_slfs_unlink(const char *filename);
13699int fs_slfs_rename(const char *from, const char *to);
13700
13701void fs_slfs_set_file_size(
const char *
name,
size_t size);
13702void fs_slfs_set_file_flags(
const char *
name, uint32_t flags, uint32_t *token);
13703void fs_slfs_unset_file_flags(
const char *
name);
13704
13705#endif
13706
13707#endif
13708#ifdef MG_MODULE_LINES
13709#line 1 "common/platforms/simplelink/sl_fs_slfs.c"
13710#endif
13711
13712
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728
13729
13730#if defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS)
13731
13732
13733
13734#include <errno.h>
13735
13736#if CS_PLATFORM == CS_P_CC3200
13737#include <inc/hw_types.h>
13738#endif
13739
13740
13741
13742
13743#if SL_MAJOR_VERSION_NUM < 2
13744int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token) {
13745 _i32 fh;
13746 _i32 r = sl_FsOpen(fname, flags, (unsigned long *) token, &fh);
13747 return (r < 0 ? r : fh);
13748}
13749#else
13750int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token) {
13751 return sl_FsOpen(fname, flags, (unsigned long *) token);
13752}
13753#endif
13754
13755
13756int set_errno(
int e);
13757const char *drop_dir(const char *fname, bool *is_slfs);
13758
13759
13760
13761
13762
13763#ifndef FS_SLFS_MAX_FILE_SIZE
13764#define FS_SLFS_MAX_FILE_SIZE (64 * 1024)
13765#endif
13766
13767struct sl_file_open_info {
13769 size_t size;
13770 uint32_t flags;
13771 uint32_t *token;
13772};
13773
13774struct sl_fd_info {
13775 _i32 fh;
13776 _off_t pos;
13777 size_t size;
13778};
13779
13780static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES];
13781static struct sl_file_open_info s_sl_file_open_infos[MAX_OPEN_SLFS_FILES];
13782
13783static struct sl_file_open_info *fs_slfs_find_foi(
const char *
name,
13785
13786static int sl_fs_to_errno(_i32 r) {
13787 DBG((
"SL error: %d", (
int) r));
13788 switch (r) {
13789 case SL_FS_OK:
13790 return 0;
13791 case SL_ERROR_FS_FILE_NAME_EXIST:
13792 return EEXIST;
13793 case SL_ERROR_FS_WRONG_FILE_NAME:
13794 return EINVAL;
13795 case SL_ERROR_FS_NO_AVAILABLE_NV_INDEX:
13796 case SL_ERROR_FS_NOT_ENOUGH_STORAGE_SPACE:
13797 return ENOSPC;
13798 case SL_ERROR_FS_FAILED_TO_ALLOCATE_MEM:
13799 return ENOMEM;
13800 case SL_ERROR_FS_FILE_NOT_EXISTS:
13801 return ENOENT;
13802 case SL_ERROR_FS_NOT_SUPPORTED:
13803 return ENOTSUP;
13804 }
13805 return ENXIO;
13806}
13807
13808int fs_slfs_open(const char *pathname, int flags, mode_t mode) {
13809 int fd;
13810 for (fd = 0; fd < MAX_OPEN_SLFS_FILES; fd++) {
13811 if (s_sl_fds[fd].fh <= 0) break;
13812 }
13813 if (fd >= MAX_OPEN_SLFS_FILES) return set_errno(ENOMEM);
13814 struct sl_fd_info *fi = &s_sl_fds[fd];
13815
13816
13817
13818
13819
13820 pathname = drop_dir(pathname, NULL);
13821
13822 _u32 am = 0;
13823 fi->size = (size_t) -1;
13824 int rw = (flags & 3);
13825 size_t new_size = 0;
13826 struct sl_file_open_info *foi =
13827 fs_slfs_find_foi(pathname, false );
13828 if (foi != NULL) {
13829 LOG(
LL_DEBUG, (
"FOI for %s: %d 0x%x %p", pathname, (
int) foi->size,
13830 (unsigned int) foi->flags, foi->token));
13831 }
13832 if (rw == O_RDONLY) {
13833 SlFsFileInfo_t sl_fi;
13834 _i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi);
13835 if (r == SL_FS_OK) {
13836 fi->size = SL_FI_FILE_SIZE(sl_fi);
13837 }
13838 am = SL_FS_READ;
13839 } else {
13840 if (!(flags & O_TRUNC) || (flags & O_APPEND)) {
13841
13842
13843 return set_errno(ENOTSUP);
13844 }
13845 if (flags & O_CREAT) {
13846 if (foi->size > 0) {
13847 new_size = foi->size;
13848 } else {
13849 new_size = FS_SLFS_MAX_FILE_SIZE;
13850 }
13851 am = FS_MODE_OPEN_CREATE(new_size, 0);
13852 } else {
13853 am = SL_FS_WRITE;
13854 }
13855#if SL_MAJOR_VERSION_NUM >= 2
13856 am |= SL_FS_OVERWRITE;
13857#endif
13858 }
13859 uint32_t *token = NULL;
13860 if (foi != NULL) {
13861 am |= foi->flags;
13862 token = foi->token;
13863 }
13864 fi->fh = slfs_open((_u8 *) pathname, am, token);
13865 LOG(
LL_DEBUG, (
"sl_FsOpen(%s, 0x%x, %p) sz %u = %d", pathname, (
int) am,
13866 token, (unsigned int) new_size, (int) fi->fh));
13867 int r;
13868 if (fi->fh >= 0) {
13869 fi->pos = 0;
13870 r = fd;
13871 } else {
13872 r = set_errno(sl_fs_to_errno(fi->fh));
13873 }
13874 return r;
13875}
13876
13877int fs_slfs_close(int fd) {
13878 struct sl_fd_info *fi = &s_sl_fds[fd];
13879 if (fi->fh <= 0) return set_errno(EBADF);
13880 _i32 r = sl_FsClose(fi->fh, NULL, NULL, 0);
13881 LOG(
LL_DEBUG, (
"sl_FsClose(%d) = %d", (
int) fi->fh, (
int) r));
13882 s_sl_fds[fd].fh = -1;
13883 return set_errno(sl_fs_to_errno(r));
13884}
13885
13886ssize_t fs_slfs_read(
int fd,
void *buf,
size_t count) {
13887 struct sl_fd_info *fi = &s_sl_fds[fd];
13888 if (fi->fh <= 0) return set_errno(EBADF);
13889
13890
13891 if (fi->pos == fi->size) return 0;
13892 _i32 r = sl_FsRead(fi->fh, fi->pos, buf,
count);
13893 DBG((
"sl_FsRead(%d, %d, %d) = %d", (
int) fi->fh, (
int) fi->pos, (
int)
count,
13894 (int) r));
13895 if (r >= 0) {
13896 fi->pos += r;
13897 return r;
13898 }
13899 return set_errno(sl_fs_to_errno(r));
13900}
13901
13902ssize_t fs_slfs_write(
int fd,
const void *buf,
size_t count) {
13903 struct sl_fd_info *fi = &s_sl_fds[fd];
13904 if (fi->fh <= 0) return set_errno(EBADF);
13905 _i32 r = sl_FsWrite(fi->fh, fi->pos, (_u8 *) buf,
count);
13906 DBG((
"sl_FsWrite(%d, %d, %d) = %d", (
int) fi->fh, (
int) fi->pos, (
int)
count,
13907 (int) r));
13908 if (r >= 0) {
13909 fi->pos += r;
13910 return r;
13911 }
13912 return set_errno(sl_fs_to_errno(r));
13913}
13914
13915int fs_slfs_stat(const char *pathname, struct stat *s) {
13916 SlFsFileInfo_t sl_fi;
13917
13918
13919
13920
13921 pathname = drop_dir(pathname, NULL);
13922 _i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi);
13923 if (r == SL_FS_OK) {
13924 s->st_mode = S_IFREG | 0666;
13925 s->st_nlink = 1;
13926 s->st_size = SL_FI_FILE_SIZE(sl_fi);
13927 return 0;
13928 }
13929 return set_errno(sl_fs_to_errno(r));
13930}
13931
13932int fs_slfs_fstat(int fd, struct stat *s) {
13933 struct sl_fd_info *fi = &s_sl_fds[fd];
13934 if (fi->fh <= 0) return set_errno(EBADF);
13935 s->st_mode = 0666;
13936 s->st_mode = S_IFREG | 0666;
13937 s->st_nlink = 1;
13938 s->st_size = fi->size;
13939 return 0;
13940}
13941
13942off_t fs_slfs_lseek(
int fd, off_t
offset,
int whence) {
13943 if (s_sl_fds[fd].fh <= 0) return set_errno(EBADF);
13944 switch (whence) {
13945 case SEEK_SET:
13946 s_sl_fds[fd].pos =
offset;
13947 break;
13948 case SEEK_CUR:
13949 s_sl_fds[fd].pos +=
offset;
13950 break;
13951 case SEEK_END:
13952 return set_errno(ENOTSUP);
13953 }
13954 return 0;
13955}
13956
13957int fs_slfs_unlink(const char *pathname) {
13958
13959
13960
13961
13962 pathname = drop_dir(pathname, NULL);
13963 return set_errno(sl_fs_to_errno(sl_FsDel((const _u8 *) pathname, 0)));
13964}
13965
13966int fs_slfs_rename(const char *from, const char *to) {
13967 return set_errno(ENOTSUP);
13968}
13969
13970static struct sl_file_open_info *fs_slfs_find_foi(
const char *
name,
13973 for (
i = 0;
i < MAX_OPEN_SLFS_FILES;
i++) {
13974 if (s_sl_file_open_infos[
i].
name != NULL &&
13975 strcmp(drop_dir(s_sl_file_open_infos[
i].
name, NULL),
name) == 0) {
13976 break;
13977 }
13978 }
13979 if (
i != MAX_OPEN_SLFS_FILES)
return &s_sl_file_open_infos[
i];
13980 if (!
create)
return NULL;
13981 for (
i = 0;
i < MAX_OPEN_SLFS_FILES;
i++) {
13982 if (s_sl_file_open_infos[
i].
name == NULL)
break;
13983 }
13984 if (
i == MAX_OPEN_SLFS_FILES) {
13986 }
13987 if (s_sl_file_open_infos[
i].
name != NULL) {
13988 free(s_sl_file_open_infos[
i].
name);
13989 }
13990 s_sl_file_open_infos[
i].name = strdup(
name);
13991 return &s_sl_file_open_infos[
i];
13992}
13993
13994void fs_slfs_set_file_size(
const char *
name,
size_t size) {
13995 struct sl_file_open_info *foi = fs_slfs_find_foi(
name,
true );
13996 foi->size = size;
13997}
13998
13999void fs_slfs_set_file_flags(
const char *
name, uint32_t flags, uint32_t *token) {
14000 struct sl_file_open_info *foi = fs_slfs_find_foi(
name,
true );
14001 foi->flags = flags;
14002 foi->token = token;
14003}
14004
14005void fs_slfs_unset_file_flags(
const char *
name) {
14006 struct sl_file_open_info *foi = fs_slfs_find_foi(
name,
false );
14007 if (foi == NULL) return;
14008 free(foi->name);
14009 memset(foi, 0, sizeof(*foi));
14010}
14011
14012#endif
14013#ifdef MG_MODULE_LINES
14014#line 1 "common/platforms/simplelink/sl_fs.c"
14015#endif
14016
14017
14018
14019
14020
14021
14022
14023
14024
14025
14026
14027
14028
14029
14030
14031
14032
14033#if MG_NET_IF == MG_NET_IF_SIMPLELINK && \
14034 (defined(MG_FS_SLFS) || defined(MG_FS_SPIFFS))
14035
14036int set_errno(
int e) {
14038 return (
e == 0 ? 0 : -1);
14039}
14040
14041const char *drop_dir(const char *fname, bool *is_slfs) {
14042 if (is_slfs != NULL) {
14043 *is_slfs = (strncmp(fname, "SL:", 3) == 0);
14044 if (*is_slfs) fname += 3;
14045 }
14046
14047 if (fname[0] == '.' && fname[1] == '/') {
14048 fname += 2;
14049 }
14050
14051
14052
14053
14054 if (fname[0] == '/' && strchr(fname + 1, '/') == NULL) {
14055 fname++;
14056 }
14057 return fname;
14058}
14059
14060#if !defined(MG_FS_NO_VFS)
14061
14062#include <errno.h>
14063#include <stdbool.h>
14064#include <stdio.h>
14065#include <stdlib.h>
14066#include <string.h>
14067#ifdef __TI_COMPILER_VERSION__
14068#include <file.h>
14069#endif
14070
14071
14072
14073
14074#ifdef CC3200_FS_SPIFFS
14075
14076#endif
14077
14078#ifdef MG_FS_SLFS
14079
14080#endif
14081
14082#define NUM_SYS_FDS 3
14083#define SPIFFS_FD_BASE 10
14084#define SLFS_FD_BASE 100
14085
14086#if !defined(MG_UART_CHAR_PUT) && !defined(MG_UART_WRITE)
14087#if CS_PLATFORM == CS_P_CC3200
14088#include <inc/hw_types.h>
14089#include <inc/hw_memmap.h>
14090#include <driverlib/rom.h>
14091#include <driverlib/rom_map.h>
14092#include <driverlib/uart.h>
14093#define MG_UART_CHAR_PUT(fd, c) MAP_UARTCharPut(UARTA0_BASE, c);
14094#else
14095#define MG_UART_WRITE(fd, buf, len)
14096#endif
14097#endif
14098
14099enum fd_type {
14100 FD_INVALID,
14101 FD_SYS,
14102#ifdef CC3200_FS_SPIFFS
14103 FD_SPIFFS,
14104#endif
14105#ifdef MG_FS_SLFS
14106 FD_SLFS
14107#endif
14108};
14109static int fd_type(int fd) {
14110 if (fd >= 0 && fd < NUM_SYS_FDS) return FD_SYS;
14111#ifdef CC3200_FS_SPIFFS
14112 if (fd >= SPIFFS_FD_BASE && fd < SPIFFS_FD_BASE + MAX_OPEN_SPIFFS_FILES) {
14113 return FD_SPIFFS;
14114 }
14115#endif
14116#ifdef MG_FS_SLFS
14117 if (fd >= SLFS_FD_BASE && fd < SLFS_FD_BASE + MAX_OPEN_SLFS_FILES) {
14118 return FD_SLFS;
14119 }
14120#endif
14121 return FD_INVALID;
14122}
14123
14124#if MG_TI_NO_HOST_INTERFACE
14125int open(const char *pathname, unsigned flags, int mode) {
14126#else
14127int _open(const char *pathname, int flags, mode_t mode) {
14128#endif
14129 int fd = -1;
14130 bool is_sl;
14131 const char *fname = drop_dir(pathname, &is_sl);
14132 if (is_sl) {
14133#ifdef MG_FS_SLFS
14134 fd = fs_slfs_open(fname, flags, mode);
14135 if (fd >= 0) fd += SLFS_FD_BASE;
14136#endif
14137 } else {
14138#ifdef CC3200_FS_SPIFFS
14139 fd = fs_spiffs_open(fname, flags, mode);
14140 if (fd >= 0) fd += SPIFFS_FD_BASE;
14141#endif
14142 }
14144 ("open(%s, 0x%x) = %d, fname = %s", pathname, flags, fd, fname));
14145 return fd;
14146}
14147
14148int _stat(const char *pathname, struct stat *st) {
14149 int res = -1;
14150 bool is_sl;
14151 const char *fname = drop_dir(pathname, &is_sl);
14152 memset(st, 0, sizeof(*st));
14153
14154 if (fname[0] == '\0' || strcmp(fname, ".") == 0) {
14155 st->st_ino = 0;
14156 st->st_mode = S_IFDIR | 0777;
14157 st->st_nlink = 1;
14158 st->st_size = 0;
14159 return 0;
14160 }
14161 if (is_sl) {
14162#ifdef MG_FS_SLFS
14163 res = fs_slfs_stat(fname, st);
14164#endif
14165 } else {
14166#ifdef CC3200_FS_SPIFFS
14167 res = fs_spiffs_stat(fname, st);
14168#endif
14169 }
14170 LOG(
LL_DEBUG, (
"stat(%s) = %d; fname = %s", pathname, res, fname));
14171 return res;
14172}
14173
14174#if MG_TI_NO_HOST_INTERFACE
14175int close(int fd) {
14176#else
14177int _close(int fd) {
14178#endif
14179 int r = -1;
14180 switch (fd_type(fd)) {
14181 case FD_INVALID:
14182 r = set_errno(EBADF);
14183 break;
14184 case FD_SYS:
14185 r = set_errno(EACCES);
14186 break;
14187#ifdef CC3200_FS_SPIFFS
14188 case FD_SPIFFS:
14189 r = fs_spiffs_close(fd - SPIFFS_FD_BASE);
14190 break;
14191#endif
14192#ifdef MG_FS_SLFS
14193 case FD_SLFS:
14194 r = fs_slfs_close(fd - SLFS_FD_BASE);
14195 break;
14196#endif
14197 }
14198 DBG((
"close(%d) = %d", fd, r));
14199 return r;
14200}
14201
14202#if MG_TI_NO_HOST_INTERFACE
14203off_t lseek(
int fd, off_t
offset,
int whence) {
14204#else
14205off_t _lseek(
int fd, off_t
offset,
int whence) {
14206#endif
14207 int r = -1;
14208 switch (fd_type(fd)) {
14209 case FD_INVALID:
14210 r = set_errno(EBADF);
14211 break;
14212 case FD_SYS:
14213 r = set_errno(ESPIPE);
14214 break;
14215#ifdef CC3200_FS_SPIFFS
14216 case FD_SPIFFS:
14217 r = fs_spiffs_lseek(fd - SPIFFS_FD_BASE,
offset, whence);
14218 break;
14219#endif
14220#ifdef MG_FS_SLFS
14221 case FD_SLFS:
14222 r = fs_slfs_lseek(fd - SLFS_FD_BASE,
offset, whence);
14223 break;
14224#endif
14225 }
14226 DBG((
"lseek(%d, %d, %d) = %d", fd, (
int)
offset, whence, r));
14227 return r;
14228}
14229
14230int _fstat(int fd, struct stat *s) {
14231 int r = -1;
14232 memset(s, 0, sizeof(*s));
14233 switch (fd_type(fd)) {
14234 case FD_INVALID:
14235 r = set_errno(EBADF);
14236 break;
14237 case FD_SYS: {
14238
14239 memset(s, 0, sizeof(*s));
14240 s->st_ino = fd;
14241 s->st_mode = S_IFCHR | 0666;
14242 r = 0;
14243 break;
14244 }
14245#ifdef CC3200_FS_SPIFFS
14246 case FD_SPIFFS:
14247 r = fs_spiffs_fstat(fd - SPIFFS_FD_BASE, s);
14248 break;
14249#endif
14250#ifdef MG_FS_SLFS
14251 case FD_SLFS:
14252 r = fs_slfs_fstat(fd - SLFS_FD_BASE, s);
14253 break;
14254#endif
14255 }
14256 DBG((
"fstat(%d) = %d", fd, r));
14257 return r;
14258}
14259
14260#if MG_TI_NO_HOST_INTERFACE
14261int read(
int fd,
char *buf,
unsigned count) {
14262#else
14263ssize_t _read(
int fd,
void *buf,
size_t count) {
14264#endif
14265 int r = -1;
14266 switch (fd_type(fd)) {
14267 case FD_INVALID:
14268 r = set_errno(EBADF);
14269 break;
14270 case FD_SYS: {
14271 if (fd != 0) {
14272 r = set_errno(EACCES);
14273 break;
14274 }
14275
14276 r = set_errno(ENOTSUP);
14277 break;
14278 }
14279#ifdef CC3200_FS_SPIFFS
14280 case FD_SPIFFS:
14281 r = fs_spiffs_read(fd - SPIFFS_FD_BASE, buf,
count);
14282 break;
14283#endif
14284#ifdef MG_FS_SLFS
14285 case FD_SLFS:
14286 r = fs_slfs_read(fd - SLFS_FD_BASE, buf,
count);
14287 break;
14288#endif
14289 }
14290 DBG((
"read(%d, %u) = %d", fd,
count, r));
14291 return r;
14292}
14293
14294#if MG_TI_NO_HOST_INTERFACE
14295int write(
int fd,
const char *buf,
unsigned count) {
14296#else
14297ssize_t _write(
int fd,
const void *buf,
size_t count) {
14298#endif
14299 int r = -1;
14300 switch (fd_type(fd)) {
14301 case FD_INVALID:
14302 r = set_errno(EBADF);
14303 break;
14304 case FD_SYS: {
14305 if (fd == 0) {
14306 r = set_errno(EACCES);
14307 break;
14308 }
14309#ifdef MG_UART_WRITE
14310 MG_UART_WRITE(fd, buf,
count);
14311#elif defined(MG_UART_CHAR_PUT)
14312 {
14315 const char c = ((
const char *) buf)[
i];
14316 if (
c ==
'\n') MG_UART_CHAR_PUT(fd,
'\r');
14317 MG_UART_CHAR_PUT(fd,
c);
14318 }
14319 }
14320#endif
14322 break;
14323 }
14324#ifdef CC3200_FS_SPIFFS
14325 case FD_SPIFFS:
14326 r = fs_spiffs_write(fd - SPIFFS_FD_BASE, buf,
count);
14327 break;
14328#endif
14329#ifdef MG_FS_SLFS
14330 case FD_SLFS:
14331 r = fs_slfs_write(fd - SLFS_FD_BASE, buf,
count);
14332 break;
14333#endif
14334 }
14335 return r;
14336}
14337
14338
14339
14340
14341
14342#if MG_TI_NO_HOST_INTERFACE || defined(_NEWLIB_VERSION)
14343int rename(const char *frompath, const char *topath) {
14344 int r = -1;
14345 bool is_sl_from, is_sl_to;
14346 const char *from = drop_dir(frompath, &is_sl_from);
14347 const char *to = drop_dir(topath, &is_sl_to);
14348 if (is_sl_from || is_sl_to) {
14349 set_errno(ENOTSUP);
14350 } else {
14351#ifdef CC3200_FS_SPIFFS
14352 r = fs_spiffs_rename(from, to);
14353#endif
14354 }
14355 DBG((
"rename(%s, %s) = %d", from, to, r));
14356 return r;
14357}
14358#endif
14359
14360#if MG_TI_NO_HOST_INTERFACE
14361int unlink(const char *pathname) {
14362#else
14363int _unlink(const char *pathname) {
14364#endif
14365 int r = -1;
14366 bool is_sl;
14367 const char *fname = drop_dir(pathname, &is_sl);
14368 if (is_sl) {
14369#ifdef MG_FS_SLFS
14370 r = fs_slfs_unlink(fname);
14371#endif
14372 } else {
14373#ifdef CC3200_FS_SPIFFS
14374 r = fs_spiffs_unlink(fname);
14375#endif
14376 }
14377 DBG((
"unlink(%s) = %d, fname = %s", pathname, r, fname));
14378 return r;
14379}
14380
14381#ifdef CC3200_FS_SPIFFS
14382DIR *opendir(
const char *dir_name) {
14384 bool is_sl;
14385 drop_dir(dir_name, &is_sl);
14386 if (is_sl) {
14387 r = NULL;
14388 set_errno(ENOTSUP);
14389 } else {
14390 r = fs_spiffs_opendir(dir_name);
14391 }
14392 DBG((
"opendir(%s) = %p", dir_name, r));
14393 return r;
14394}
14395
14396struct dirent *readdir(
DIR *dir) {
14397 struct dirent *res = fs_spiffs_readdir(dir);
14398 DBG((
"readdir(%p) = %p", dir, res));
14399 return res;
14400}
14401
14402int closedir(
DIR *dir) {
14403 int res = fs_spiffs_closedir(dir);
14404 DBG((
"closedir(%p) = %d", dir, res));
14405 return res;
14406}
14407
14408int rmdir(
const char *path) {
14409 return fs_spiffs_rmdir(path);
14410}
14411
14412int mkdir(const char *path, mode_t mode) {
14413 (void) path;
14414 (void) mode;
14415
14416 return (strlen(path) == 1 && *path == '.') ? 0 : ENOTDIR;
14417}
14418#endif
14419
14420int sl_fs_init(void) {
14421 int ret = 1;
14422#ifdef __TI_COMPILER_VERSION__
14423#ifdef MG_FS_SLFS
14424#pragma diag_push
14425#pragma diag_suppress 169
14426
14427 ret = (add_device("SL", _MSA, fs_slfs_open, fs_slfs_close, fs_slfs_read,
14428 fs_slfs_write, fs_slfs_lseek, fs_slfs_unlink,
14429 fs_slfs_rename) == 0);
14430#pragma diag_pop
14431#endif
14432#endif
14433 return ret;
14434}
14435
14436#endif
14437#endif
14438
14439#ifdef MG_MODULE_LINES
14440#line 1 "common/platforms/simplelink/sl_socket.c"
14441#endif
14442
14443
14444
14445
14446
14447
14448
14449
14450
14451
14452
14453
14454
14455
14456
14457
14458
14459#if MG_NET_IF == MG_NET_IF_SIMPLELINK
14460
14461#include <errno.h>
14462#include <stdio.h>
14463
14464
14465
14466const char *
inet_ntop(
int af,
const void *src,
char *dst, socklen_t size) {
14467 int res;
14468 struct in_addr *in = (struct in_addr *) src;
14469 if (af != AF_INET) {
14470 errno = ENOTSUP;
14471 return NULL;
14472 }
14473 res = snprintf(dst, size, "%lu.%lu.%lu.%lu", SL_IPV4_BYTE(in->s_addr, 0),
14474 SL_IPV4_BYTE(in->s_addr, 1), SL_IPV4_BYTE(in->s_addr, 2),
14475 SL_IPV4_BYTE(in->s_addr, 3));
14476 return res > 0 ? dst : NULL;
14477}
14478
14480 static char a[16];
14481 return (
char *)
inet_ntop(AF_INET, &
n, a,
sizeof(a));
14482}
14483
14484int inet_pton(
int af,
const char *src,
void *dst) {
14485 uint32_t a0, a1, a2, a3;
14486 uint8_t *db = (uint8_t *) dst;
14487 if (af != AF_INET) {
14488 errno = ENOTSUP;
14489 return 0;
14490 }
14491 if (sscanf(src, "%lu.%lu.%lu.%lu", &a0, &a1, &a2, &a3) != 4) {
14492 return 0;
14493 }
14494 *db = a3;
14495 *(db + 1) = a2;
14496 *(db + 2) = a1;
14497 *(db + 3) = a0;
14498 return 1;
14499}
14500
14501#endif
14502#ifdef MG_MODULE_LINES
14503#line 1 "common/platforms/simplelink/sl_mg_task.c"
14504#endif
14505#if MG_NET_IF == MG_NET_IF_SIMPLELINK && !defined(MG_SIMPLELINK_NO_OSI)
14506
14507
14508
14509#include <oslib/osi.h>
14510
14513};
14518};
14520static void mg_task(
void *arg);
14521
14522bool mg_start_task(
int priority,
int stack_size, mg_init_cb mg_init) {
14523 if (osi_MsgQCreate(&
s_mg_q,
"MG",
sizeof(
struct mg_q_msg), 16) != OSI_OK) {
14524 return false;
14525 }
14526 if (osi_TaskCreate(
mg_task, (
const signed char *)
"MG", stack_size,
14527 (void *) mg_init, priority, NULL) != OSI_OK) {
14528 return false;
14529 }
14530 return true;
14531}
14532
14533static void mg_task(
void *arg) {
14535 mg_init_cb mg_init = (mg_init_cb) arg;
14537 mg_init(&mgr);
14538 while (1) {
14541 if (osi_MsgQRead(&
s_mg_q, &msg, 1) != OSI_OK)
continue;
14542 switch (msg.type) {
14544 msg.cb(&mgr, msg.arg);
14545 }
14546 }
14547 }
14548}
14549
14552 osi_MsgQWrite(&
s_mg_q, &msg, OSI_NO_WAIT);
14553}
14554
14555#endif
14556
14557#ifdef MG_MODULE_LINES
14558#line 1 "common/platforms/simplelink/sl_net_if.h"
14559#endif
14560
14561
14562
14563
14564
14565
14566
14567
14568
14569
14570
14571
14572
14573
14574
14575
14576
14577#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_
14578#define CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_
14579
14580
14581
14582#ifdef __cplusplus
14583extern "C" {
14584#endif
14585
14586#ifndef MG_ENABLE_NET_IF_SIMPLELINK
14587#define MG_ENABLE_NET_IF_SIMPLELINK MG_NET_IF == MG_NET_IF_SIMPLELINK
14588#endif
14589
14591
14592#ifdef __cplusplus
14593}
14594#endif
14595
14596#endif
14597#ifdef MG_MODULE_LINES
14598#line 1 "common/platforms/simplelink/sl_net_if.c"
14599#endif
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619#if MG_ENABLE_NET_IF_SIMPLELINK
14620
14621
14622
14623
14624#define MG_TCP_RECV_BUFFER_SIZE 1024
14625#define MG_UDP_RECV_BUFFER_SIZE 1500
14626
14629 int proto);
14630
14632 SlSockNonblocking_t opt;
14633#if SL_MAJOR_VERSION_NUM < 2
14634 opt.NonblockingEnabled = 1;
14635#else
14636 opt.NonBlockingEnabled = 1;
14637#endif
14638 sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &opt, sizeof(opt));
14639}
14640
14642 return (
n < 0 &&
n != SL_ERROR_BSD_EALREADY &&
n != SL_ERROR_BSD_EAGAIN);
14643}
14644
14647 int proto = 0;
14648#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
14650#endif
14651 sock_t sock = sl_Socket(AF_INET, SOCK_STREAM, proto);
14652 if (sock < 0) {
14654 goto out;
14655 }
14657#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
14658 nc->
err = sl_set_ssl_opts(sock, nc);
14659 if (nc->
err != 0)
goto out;
14660#endif
14661 nc->
err = sl_Connect(sock, &sa->
sa,
sizeof(sa->
sin));
14662out:
14663 DBG((
"%p to %s:%d sock %d %d err %d", nc,
inet_ntoa(sa->
sin.sin_addr),
14664 ntohs(sa->
sin.sin_port), nc->
sock, proto, nc->
err));
14665}
14666
14668 sock_t sock = sl_Socket(AF_INET, SOCK_DGRAM, 0);
14669 if (sock < 0) {
14671 return;
14672 }
14675}
14676
14679 int proto = 0;
14682 if (sock < 0) return sock;
14684 return 0;
14685}
14686
14692 return 0;
14693}
14694
14696 size_t len) {
14697 int n = (int) sl_Send(nc->
sock, buf, len, 0);
14700}
14701
14703 size_t len) {
14704 int n = sl_SendTo(nc->
sock, buf, len, 0, &nc->
sa.
sa,
sizeof(nc->
sa.
sin));
14707}
14708
14710 int n = sl_Recv(nc->
sock, buf, len, 0);
14712
14716 }
14718}
14719
14722 SlSocklen_t sa_len_t = *sa_len;
14724 (SlSockAddr_t *) sa, &sa_len_t);
14725 *sa_len = sa_len_t;
14728}
14729
14731 (void) nc;
14732 return 1;
14733}
14734
14737
14739 sl_Close(nc->
sock);
14740 }
14742}
14743
14747 socklen_t sa_len =
sizeof(
sa);
14748 sock_t sock = sl_Accept(lc->
sock, &
sa.sa, &sa_len);
14749 if (sock < 0) {
14750 DBG((
"%p: failed to accept: %d", lc, sock));
14751 return 0;
14752 }
14754 if (nc == NULL) {
14755 sl_Close(sock);
14756 return 0;
14757 }
14759 ntohs(
sa.sin.sin_port)));
14762 return 1;
14763}
14764
14765
14768 int proto) {
14769 int r;
14770 socklen_t sa_len =
14771 (
sa->sa.sa_family == AF_INET) ?
sizeof(
sa->sin) :
sizeof(
sa->sin6);
14772 sock_t sock = sl_Socket(
sa->sa.sa_family,
type, proto);
14773 if (sock < 0) return sock;
14774#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
14775 if ((r = sl_set_ssl_opts(sock, nc)) < 0) goto clean;
14776#endif
14777 if ((r = sl_Bind(sock, &
sa->sa, sa_len)) < 0)
goto clean;
14778 if (
type != SOCK_DGRAM) {
14779 if ((r = sl_Listen(sock,
SOMAXCONN)) < 0)
goto clean;
14780 }
14782clean:
14783 if (r < 0) {
14784 sl_Close(sock);
14785 sock = r;
14786 }
14787 return sock;
14788}
14789
14790#define _MG_F_FD_CAN_READ 1
14791#define _MG_F_FD_CAN_WRITE 1 << 1
14792#define _MG_F_FD_ERROR 1 << 2
14793
14795 DBG((
"%p fd=%d fd_flags=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock,
14797
14799
14803 } else {
14804
14805
14806
14809 DBG((
"%p conn res=%d", nc, nc->
err));
14810 if (nc->
err == SL_ERROR_BSD_ESECSNOVERIFY ||
14811
14812 nc->
err == SL_ERROR_BSD_ESECDATEERROR
14813#if SL_MAJOR_VERSION_NUM >= 2
14814
14815
14816
14817 ||
14818 nc->
err == SL_ERROR_BSD_ESECUNKNOWNROOTCA
14819#endif
14820 ) {
14822 }
14824 }
14825 }
14826
14828 }
14829
14833 } else {
14836 } else {
14838 }
14839 }
14840 }
14841
14844 }
14845
14846 DBG((
"%p after fd=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock, nc->
flags,
14848}
14849
14850
14854 DBG((
"%p %d", nc, sock));
14855}
14856
14858 (void) iface;
14859 DBG((
"%p using sl_Select()", iface->
mgr));
14860}
14861
14863 (void) iface;
14864}
14865
14867 (void) nc;
14868}
14869
14871 (void) nc;
14872}
14873
14877 double min_timer;
14879 struct SlTimeval_t
tv;
14880 SlFdSet_t read_set, write_set, err_set;
14882 int num_fds, num_ev = 0, num_timers = 0;
14883
14884 SL_SOCKET_FD_ZERO(&read_set);
14885 SL_SOCKET_FD_ZERO(&write_set);
14886 SL_SOCKET_FD_ZERO(&err_set);
14887
14888
14889
14890
14891
14892 min_timer = 0;
14895
14897 num_fds++;
14898
14902 SL_SOCKET_FD_SET(nc->
sock, &read_set);
14904 }
14905
14908 SL_SOCKET_FD_SET(nc->
sock, &write_set);
14909 SL_SOCKET_FD_SET(nc->
sock, &err_set);
14911 }
14912 }
14913
14917 }
14918 num_timers++;
14919 }
14920 }
14921
14922
14923
14924
14925
14926 if (num_timers > 0) {
14927 double timer_timeout_ms = (min_timer -
mg_time()) * 1000 + 1 ;
14928 if (timer_timeout_ms < timeout_ms) {
14929 timeout_ms = timer_timeout_ms;
14930 }
14931 }
14932 if (timeout_ms < 0) timeout_ms = 0;
14933
14934 tv.tv_sec = timeout_ms / 1000;
14935 tv.tv_usec = (timeout_ms % 1000) * 1000;
14936
14937 if (num_fds > 0) {
14938 num_ev = sl_Select((
int) max_fd + 1, &read_set, &write_set, &err_set, &
tv);
14939 }
14940
14942 DBG((
"sl_Select @ %ld num_ev=%d of %d, timeout=%d", (
long) now, num_ev,
14943 num_fds, timeout_ms));
14944
14946 int fd_flags = 0;
14948 if (num_ev > 0) {
14949 fd_flags =
14950 (SL_SOCKET_FD_ISSET(nc->
sock, &read_set) &&
14953 : 0) |
14955 : 0) |
14957 }
14958
14961 }
14962 }
14965 }
14966
14967 return now;
14968}
14969
14972
14973
14974
14975 if (remote) memcpy(sa, &nc->
sa,
sizeof(*sa));
14976}
14977
14979
14980
14981
14982
14983
14989 ntohs(nc->
sa.
sin.sin_port)));
14992 if (res == 0) continue;
14993
14994 }
14997 ntohs(nc->
sa.
sin.sin_port)));
14998
15000 }
15001}
15002
15003
15004#define MG_SL_IFACE_VTABLE \
15005 { \
15006 mg_sl_if_init, \
15007 mg_sl_if_free, \
15008 mg_sl_if_add_conn, \
15009 mg_sl_if_remove_conn, \
15010 mg_sl_if_poll, \
15011 mg_sl_if_listen_tcp, \
15012 mg_sl_if_listen_udp, \
15013 mg_sl_if_connect_tcp, \
15014 mg_sl_if_connect_udp, \
15015 mg_sl_if_tcp_send, \
15016 mg_sl_if_udp_send, \
15017 mg_sl_if_tcp_recv, \
15018 mg_sl_if_udp_recv, \
15019 mg_sl_if_create_conn, \
15020 mg_sl_if_destroy_conn, \
15021 mg_sl_if_sock_set, \
15022 mg_sl_if_get_conn_addr, \
15023 }
15024
15025
15027#if MG_NET_IF == MG_NET_IF_SIMPLELINK
15029#endif
15030
15031#endif
15032#ifdef MG_MODULE_LINES
15033#line 1 "common/platforms/simplelink/sl_ssl_if.c"
15034#endif
15035
15036
15037
15038
15039
15040
15041
15042
15043
15044
15045
15046
15047
15048
15049
15050
15051
15052#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
15053
15054
15055
15056#ifndef MG_SSL_IF_SIMPLELINK_SLFS_PREFIX
15057#define MG_SSL_IF_SIMPLELINK_SLFS_PREFIX "SL:"
15058#endif
15059
15060#define MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN \
15061 (sizeof(MG_SSL_IF_SIMPLELINK_SLFS_PREFIX) - 1)
15062
15063struct mg_ssl_if_ctx {
15064 char *ssl_cert;
15065 char *ssl_key;
15066 char *ssl_ca_cert;
15067 char *ssl_server_name;
15068};
15069
15070void mg_ssl_if_init() {
15071}
15072
15073enum mg_ssl_if_result mg_ssl_if_conn_init(
15074 struct mg_connection *nc,
const struct mg_ssl_if_conn_params *params,
15075 const char **err_msg) {
15076 struct mg_ssl_if_ctx *ctx =
15077 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
15078 if (ctx == NULL) {
15080 return MG_SSL_ERROR;
15081 }
15082 nc->ssl_if_data = ctx;
15083
15084 if (params->cert != NULL || params->key != NULL) {
15085 if (params->cert != NULL && params->key != NULL) {
15086 ctx->ssl_cert = strdup(params->cert);
15087 ctx->ssl_key = strdup(params->key);
15088 } else {
15090 return MG_SSL_ERROR;
15091 }
15092 }
15093 if (params->ca_cert != NULL && strcmp(params->ca_cert, "*") != 0) {
15094 ctx->ssl_ca_cert = strdup(params->ca_cert);
15095 }
15096
15097 if (params->server_name != NULL) {
15098 ctx->ssl_server_name = strdup(params->server_name);
15099 }
15100 return MG_SSL_OK;
15101}
15102
15103enum mg_ssl_if_result mg_ssl_if_conn_accept(
struct mg_connection *nc,
15105
15106 (void) nc;
15107 (void) lc;
15108 return MG_SSL_OK;
15109}
15110
15111enum mg_ssl_if_result mg_ssl_if_handshake(
struct mg_connection *nc) {
15112
15113 return MG_SSL_OK;
15114}
15115
15116int mg_ssl_if_read(
struct mg_connection *nc,
void *buf,
size_t len) {
15117
15121}
15122
15123int mg_ssl_if_write(
struct mg_connection *nc,
const void *buf,
size_t len) {
15124
15126}
15127
15128void mg_ssl_if_conn_close_notify(
struct mg_connection *nc) {
15129
15130 (void) nc;
15131}
15132
15134 struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
15135 if (ctx == NULL) return;
15136 nc->ssl_if_data = NULL;
15140 MG_FREE(ctx->ssl_server_name);
15141 memset(ctx, 0, sizeof(*ctx));
15143}
15144
15145bool pem_to_der(const char *pem_file, const char *der_file) {
15146 bool ret = false;
15147 FILE *pf = NULL, *df = NULL;
15148 bool writing = false;
15149 pf = fopen(pem_file, "r");
15150 if (pf == NULL) goto clean;
15151 remove(der_file);
15152 fs_slfs_set_file_size(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN, 2048);
15153 df = fopen(der_file, "w");
15154 fs_slfs_unset_file_flags(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN);
15155 if (df == NULL) goto clean;
15156 while (1) {
15157 char pem_buf[70];
15158 char der_buf[48];
15159 if (!fgets(pem_buf, sizeof(pem_buf), pf)) break;
15160 if (writing) {
15161 if (strstr(pem_buf, "-----END ") != NULL) {
15162 ret = true;
15163 break;
15164 }
15165 int l = 0;
15166 while (!isspace((unsigned int) pem_buf[l])) l++;
15167 int der_len = 0;
15169 der_buf, &der_len);
15170 if (der_len <= 0) break;
15171 if (fwrite(der_buf, 1, der_len, df) != der_len) break;
15172 } else if (strstr(pem_buf, "-----BEGIN ") != NULL) {
15173 writing = true;
15174 }
15175 }
15176
15177clean:
15178 if (pf != NULL) fclose(pf);
15179 if (df != NULL) {
15180 fclose(df);
15181 if (!ret) remove(der_file);
15182 }
15183 return ret;
15184}
15185
15186#if MG_ENABLE_FILESYSTEM && defined(MG_FS_SLFS)
15187
15188static char *sl_pem2der(const char *pem_file) {
15189 const char *pem_ext = strstr(pem_file, ".pem");
15190 if (pem_ext == NULL || *(pem_ext + 4) != '\0') {
15191 return strdup(pem_file);
15192 }
15193 char *der_file = NULL;
15194
15195 int l =
mg_asprintf(&der_file, 0, MG_SSL_IF_SIMPLELINK_SLFS_PREFIX
"%.*s.der",
15196 (int) (pem_ext - pem_file), pem_file);
15197 if (der_file == NULL) return NULL;
15198 bool result = false;
15199 cs_stat_t st;
15200 if (
mg_stat(der_file, &st) != 0) {
15201 result = pem_to_der(pem_file, der_file);
15202 LOG(
LL_DEBUG, (
"%s -> %s = %d", pem_file, der_file, result));
15203 } else {
15204
15205 result = true;
15206 }
15207 if (result) {
15208
15209 memmove(der_file, der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN,
15210 l - 2 );
15211 } else {
15213 der_file = NULL;
15214 }
15215 return der_file;
15216}
15217#else
15218static char *sl_pem2der(const char *pem_file) {
15219 return strdup(pem_file);
15220}
15221#endif
15222
15224 int err;
15225 const struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
15226 DBG((
"%p ssl ctx: %p", nc, ctx));
15227
15228 if (ctx == NULL) return 0;
15229 DBG((
"%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert :
"-"),
15230 (ctx->ssl_key ? ctx->ssl_cert : "-"),
15231 (ctx->ssl_ca_cert ? ctx->ssl_ca_cert : "-"),
15232 (ctx->ssl_server_name ? ctx->ssl_server_name : "-")));
15233 if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) {
15234 char *ssl_cert = sl_pem2der(ctx->ssl_cert), *ssl_key = NULL;
15235 if (ssl_cert != NULL) {
15236 err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
15237 SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert,
15238 strlen(ssl_cert));
15240 LOG(
LL_DEBUG, (
"CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err));
15241 ssl_key = sl_pem2der(ctx->ssl_key);
15242 if (ssl_key != NULL) {
15243 err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
15244 SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key,
15245 strlen(ssl_key));
15247 LOG(
LL_DEBUG, (
"PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err));
15248 } else {
15249 err = -1;
15250 }
15251 } else {
15252 err = -1;
15253 }
15254 if (err != 0) return err;
15255 }
15256 if (ctx->ssl_ca_cert != NULL) {
15257 if (ctx->ssl_ca_cert[0] != '\0') {
15258 char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
15259 if (ssl_ca_cert != NULL) {
15260 err =
15261 sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME,
15262 ssl_ca_cert, strlen(ssl_ca_cert));
15263 LOG(
LL_DEBUG, (
"CA_FILE_NAME %s -> %d", ssl_ca_cert, err));
15264 } else {
15265 err = -1;
15266 }
15268 if (err != 0) return err;
15269 }
15270 }
15271 if (ctx->ssl_server_name != NULL) {
15272 err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
15273 SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
15274 ctx->ssl_server_name, strlen(ctx->ssl_server_name));
15275 DBG((
"DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err));
15276
15277
15278
15279
15280 if (err != 0 && err != SL_ERROR_BSD_ENOPROTOOPT) return err;
15281 }
15282 return 0;
15283}
15284
15285#endif
15286#ifdef MG_MODULE_LINES
15287#line 1 "common/platforms/lwip/mg_lwip_net_if.h"
15288#endif
15289
15290
15291
15292
15293
15294
15295
15296
15297
15298
15299
15300
15301
15302
15303
15304
15305
15306#ifndef CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_
15307#define CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_
15308
15309#ifndef MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
15310#define MG_ENABLE_NET_IF_LWIP_LOW_LEVEL MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
15311#endif
15312
15313#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
15314
15315#include <stdint.h>
15316
15318
15322 union {
15323 struct tcp_pcb *tcp;
15324 struct udp_pcb *udp;
15330
15332
15334
15336};
15337
15344};
15345
15347
15348
15350
15351#endif
15352
15353#endif
15354#ifdef MG_MODULE_LINES
15355#line 1 "common/platforms/lwip/mg_lwip_net_if.c"
15356#endif
15357
15358
15359
15360
15361
15362
15363
15364
15365
15366
15367
15368
15369
15370
15371
15372
15373
15374#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
15375
15376
15377
15378#include <lwip/init.h>
15379#include <lwip/pbuf.h>
15380#include <lwip/tcp.h>
15381#include <lwip/tcpip.h>
15382#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
15383#include <lwip/priv/tcp_priv.h>
15384#include <lwip/priv/tcpip_priv.h>
15385#else
15386#include <lwip/tcp_impl.h>
15387#endif
15388#include <lwip/udp.h>
15389
15390
15391
15392
15393
15394
15395
15396#ifndef ip_2_ip4
15397#ifdef ipX_2_ip
15398#define ip_2_ip4(addr) ipX_2_ip(addr)
15399#else
15400#define ip_2_ip4(addr) (addr)
15401#endif
15402#endif
15403
15404
15405
15406
15407
15408#if MG_ENABLE_IPV6
15409#define TCP_NEW tcp_new_ip6
15410#define TCP_BIND tcp_bind_ip6
15411#define UDP_BIND udp_bind_ip6
15412#define IPADDR_NTOA(x) ip6addr_ntoa((const ip6_addr_t *)(x))
15413#define SET_ADDR(dst, src) \
15414 memcpy((dst)->sin6.sin6_addr.s6_addr, (src)->ip6.addr, \
15415 sizeof((dst)->sin6.sin6_addr.s6_addr))
15416#else
15417#define TCP_NEW tcp_new
15418#define TCP_BIND tcp_bind
15419#define UDP_BIND udp_bind
15420#define IPADDR_NTOA ipaddr_ntoa
15421#define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = ip_2_ip4(src)->addr
15422#endif
15423
15424#if !NO_SYS
15425#if LWIP_TCPIP_CORE_LOCKING
15426
15427
15429 tcpip_api_call((tcpip_api_call_fn) fn, (struct tcpip_api_call_data *) arg);
15430}
15431#else
15435 void (*
fn)(
void *);
15437};
15443}
15449}
15450#endif
15451#else
15452#define mg_lwip_netif_run_on_tcpip(fn, arg) (fn)(arg)
15453#endif
15454
15460
15461
15462#ifdef MGOS
15465#else
15466#define mgos_lock()
15467#define mgos_unlock()
15468#endif
15469
15471
15472#if LWIP_TCP_KEEPALIVE
15473void mg_lwip_set_keepalive_params(
struct mg_connection *nc,
int idle,
15474 int interval,
int count) {
15476 return;
15477 }
15479 struct tcp_pcb *tpcb = cs->pcb.tcp;
15480 if (idle > 0 && interval > 0 &&
count > 0) {
15481 tpcb->keep_idle = idle * 1000;
15482 tpcb->keep_intvl = interval * 1000;
15483 tpcb->keep_cnt =
count;
15484 tpcb->so_options |= SOF_KEEPALIVE;
15485 } else {
15486 tpcb->so_options &= ~SOF_KEEPALIVE;
15487 }
15488}
15489#elif !defined(MG_NO_LWIP_TCP_KEEPALIVE)
15490#warning LWIP TCP keepalive is disabled. Please consider enabling it.
15491#endif
15492
15495 DBG((
"%p connect to %s:%u = %d", nc,
IPADDR_NTOA(ipX_2_ip(&tpcb->remote_ip)),
15496 tpcb->remote_port,
err));
15497 if (nc == NULL) {
15498 tcp_abort(tpcb);
15499 return ERR_ARG;
15500 }
15503#if LWIP_TCP_KEEPALIVE
15504 if (
err == 0) mg_lwip_set_keepalive_params(
nc, 60, 10, 6);
15505#endif
15507 return ERR_OK;
15508}
15509
15512 DBG((
"%p conn error %d", nc,
err));
15515 cs->pcb.tcp = NULL;
15519 } else {
15521 }
15522}
15523
15525 struct pbuf *p, err_t
err) {
15529 DBG((
"%p %p %p %p %u %d",
nc, cs, tpcb, p, (p != NULL ? p->tot_len : 0),
15531 if (p == NULL) {
15534
15535
15536
15537
15539 } else {
15541 }
15542 } else {
15543
15544 }
15545 return ERR_OK;
15546 }
else if (
nc == NULL) {
15547 tcp_abort(tpcb);
15548 return ERR_ARG;
15549 }
15550
15551
15552
15553
15554 if (p->next != NULL) {
15555 struct pbuf *
q = p->next;
15556 for (;
q != NULL;
q =
q->next) pbuf_ref(
q);
15557 }
15561 }
else if (pbuf_clen(cs->
rx_chain) >= 4) {
15562
15563
15564
15565 struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
15566 if (np != NULL) {
15567 pbuf_copy(np, p);
15568 pbuf_free(p);
15569 p = np;
15570 }
15571 }
15574 (void) err;
15575 return ERR_OK;
15576}
15577
15579 u16_t num_sent) {
15581 DBG((
"%p %p %u %p %p", nc, tpcb, num_sent, tpcb->unsent, tpcb->unacked));
15582 if (nc == NULL) return ERR_OK;
15584 nc->
send_mbuf.
len == 0 && tpcb->unsent == NULL && tpcb->unacked == NULL) {
15586 }
15589 }
15590 (void) num_sent;
15591 return ERR_OK;
15592}
15593
15597};
15598
15604
15606 struct tcp_pcb *tpcb =
TCP_NEW();
15608 ip_addr_t *ip = (ip_addr_t *) &sa->
sin.sin_addr.s_addr;
15609 u16_t port = ntohs(sa->
sin.sin_port);
15610 tcp_arg(tpcb, nc);
15615 DBG((
"%p tcp_bind = %d", nc, cs->
err));
15616 if (cs->
err != ERR_OK) {
15618 return;
15619 }
15621 DBG((
"%p tcp_connect %p = %d", nc, tpcb, cs->
err));
15622 if (cs->
err != ERR_OK) {
15624 return;
15625 }
15626}
15627
15632}
15633
15634
15635
15636
15637
15638#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
15640 const ip_addr_t *
addr, u16_t port)
15641#else
15643 ip_addr_t *
addr, u16_t port)
15644#endif
15645{
15648
15649 struct pbuf *sap =
15651 if (sap == NULL) {
15652 pbuf_free(p);
15653 return;
15654 }
15656#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
15658#else
15659 sa->sin.sin_addr.s_addr =
addr->addr;
15660#endif
15661 sa->sin.sin_port = htons(port);
15662
15663 p = pbuf_coalesce(p, PBUF_RAW);
15664 pbuf_chain(sap, p);
15668 (void) pcb;
15669}
15670
15675 } else {
15677 }
15681 }
15682}
15683
15686
15687
15688
15689
15690 int res = 0;
15696 struct pbuf *dp = ap->next;
15698 res =
MIN(dp->len, len);
15699 pbuf_copy_partial(dp, buf, res, 0);
15700 pbuf_free(dp);
15701 pbuf_copy_partial(ap, sa,
MIN(*sa_len, ap->len), 0);
15702 pbuf_free(ap);
15703 }
15705 return res;
15706}
15707
15711 struct udp_pcb *upcb = udp_new();
15713 DBG((
"%p udp_bind %p = %d", nc, upcb, cs->
err));
15714 if (cs->
err == ERR_OK) {
15717 } else {
15718 udp_remove(upcb);
15719 }
15721}
15722
15725}
15726
15728 tcp_close((struct tcp_pcb *) arg);
15729}
15730
15733 if (cs->
pcb.
tcp == NULL)
return;
15735 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15737 sa.
sin.sin_port = htons(tpcb->remote_port);
15739}
15740
15744 struct tcp_pcb_listen *lpcb;
15746 ("%p conn %p from %s:%u", lc, newtpcb,
15747 IPADDR_NTOA(ipX_2_ip(&newtpcb->remote_ip)), newtpcb->remote_port));
15748 if (lc == NULL) {
15749 tcp_abort(newtpcb);
15750 return ERR_ABRT;
15751 }
15753 lpcb = (
struct tcp_pcb_listen *) lcs->
pcb.
tcp;
15754#if TCP_LISTEN_BACKLOG
15755 tcp_accepted(lpcb);
15756#endif
15758 if (nc == NULL) {
15759 tcp_abort(newtpcb);
15760 return ERR_ABRT;
15761 }
15765
15766
15767 tcp_arg(newtpcb,
nc);
15771#if LWIP_TCP_KEEPALIVE
15772 mg_lwip_set_keepalive_params(
nc, 60, 10, 6);
15773#endif
15776 (void) lpcb;
15777 return ERR_OK;
15778}
15779
15784};
15785
15791 struct tcp_pcb *tpcb =
TCP_NEW();
15792 ip_addr_t *ip = (ip_addr_t *) &sa->
sin.sin_addr.s_addr;
15793 u16_t port = ntohs(sa->
sin.sin_port);
15796 if (cs->
err != ERR_OK) {
15797 tcp_close(tpcb);
15798 ctx->ret = -1;
15799 return;
15800 }
15801 tcp_arg(tpcb, nc);
15802 tpcb = tcp_listen(tpcb);
15805 ctx->ret = 0;
15806}
15807
15812}
15813
15819 struct udp_pcb *upcb = udp_new();
15820 ip_addr_t *ip = (ip_addr_t *) &sa->
sin.sin_addr.s_addr;
15821 u16_t port = ntohs(sa->
sin.sin_port);
15824 if (cs->
err != ERR_OK) {
15825 udp_remove(upcb);
15826 ctx->ret = -1;
15827 } else {
15830 ctx->ret = 0;
15831 }
15832}
15833
15838}
15839
15845};
15846
15848 tcp_output((struct tcp_pcb *) arg);
15849}
15850
15855 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15856 size_t len =
MIN(tpcb->mss,
MIN(ctx->len, tpcb->snd_buf));
15857 size_t unsent, unacked;
15858 if (len == 0) {
15859 DBG((
"%p no buf avail %u %u %p %p", tpcb, tpcb->snd_buf, tpcb->snd_queuelen,
15860 tpcb->unsent, tpcb->unacked));
15862 ctx->ret = 0;
15863 return;
15864 }
15865 unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
15866 unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
15867
15868
15869
15870
15871
15872
15873#if CS_PLATFORM == CS_P_ESP8266
15874 if (unacked > 0) {
15875 ctx->ret = 0;
15876 return;
15877 }
15878 len =
MIN(len, (TCP_MSS - unsent));
15879#endif
15880 cs->
err = tcp_write(tpcb, ctx->data, len, TCP_WRITE_FLAG_COPY);
15881 unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
15882 unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
15883 DBG((
"%p tcp_write %u = %d, %u %u", tpcb, len, cs->
err, unsent, unacked));
15884 if (cs->
err != ERR_OK) {
15885
15886
15887
15888
15889 ctx->ret = (cs->
err == ERR_MEM ? 0 : -1);
15890 return;
15891 }
15892 ctx->ret = len;
15893 (void) unsent;
15894 (void) unacked;
15895}
15896
15901 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15902 if (tpcb == NULL) return -1;
15903 if (tpcb->snd_buf <= 0) return 0;
15905 return ctx.ret;
15906}
15907
15909 struct udp_pcb *
upcb;
15914};
15915
15919}
15920
15922 size_t len) {
15925 struct udp_pcb *upcb = cs->
pcb.
udp;
15926 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
15927#if defined(LWIP_IPV4) && LWIP_IPV4 && defined(LWIP_IPV6) && LWIP_IPV6
15928 ip_addr_t ip = {.u_addr.ip4.addr = nc->
sa.
sin.sin_addr.s_addr, .type = 0};
15929#else
15930 ip_addr_t ip = {.addr = nc->
sa.
sin.sin_addr.s_addr};
15931#endif
15932 u16_t port = ntohs(nc->
sa.
sin.sin_port);
15933 if (p == NULL) return 0;
15934 memcpy(p->payload,
data, len);
15939 return (cs->
err == ERR_OK ? (
int) len : -2);
15940}
15941
15944 int can_send = 0;
15946
15948
15949 can_send = (cs->
pcb.
udp != NULL);
15950 } else {
15951 can_send = (cs->
pcb.
tcp != NULL && cs->
pcb.
tcp->snd_buf > 0);
15952
15953#if CS_PLATFORM == CS_P_ESP8266
15954 if (cs->
pcb.
tcp->unacked != NULL) can_send = 0;
15955#endif
15956 }
15957 }
15958 return can_send;
15959}
15960
15962 struct tcp_pcb *
tpcb;
15964};
15965
15968 if (ctx->
tpcb != NULL) tcp_recved(ctx->
tpcb, ctx->
len);
15969}
15970
15973 int res = 0;
15974 char *bufp = buf;
15978 while (cs->
rx_chain != NULL && len > 0) {
15980 size_t seg_len = (seg->len - cs->
rx_offset);
15981 size_t copy_len =
MIN(len, seg_len);
15982
15983 pbuf_copy_partial(seg, bufp, copy_len, cs->
rx_offset);
15984 len -= copy_len;
15985 res += copy_len;
15986 bufp += copy_len;
15990 pbuf_free(seg);
15992 }
15993 }
15995 if (res > 0) {
15998 }
15999 return res;
16000}
16001
16005 if (cs == NULL) return 0;
16008 return 1;
16009}
16010
16012 udp_remove((struct udp_pcb *) arg);
16013}
16014
16019 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
16020 if (tpcb != NULL) {
16021 tcp_arg(tpcb, NULL);
16022 DBG((
"%p tcp_close %p", nc, tpcb));
16023 tcp_arg(tpcb, NULL);
16025 }
16029 pbuf_free(seg);
16030 }
16031 memset(cs, 0, sizeof(*cs));
16033 }
else if (nc->
listener == NULL) {
16034
16035 struct udp_pcb *upcb = cs->
pcb.
udp;
16036 if (upcb != NULL) {
16037 DBG((
"%p udp_remove %p", nc, upcb));
16039 }
16040 memset(cs, 0, sizeof(*cs));
16042 }
16044}
16045
16048 memset(sa, 0, sizeof(*sa));
16052 struct udp_pcb *upcb = cs->
pcb.
udp;
16053 if (remote) {
16054 memcpy(sa, &nc->
sa,
sizeof(*sa));
16055 } else if (upcb != NULL) {
16056 sa->
sin.sin_port = htons(upcb->local_port);
16058 }
16059 } else {
16060 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
16061 if (remote) {
16062 memcpy(sa, &nc->
sa,
sizeof(*sa));
16063 } else if (tpcb != NULL) {
16064 sa->
sin.sin_port = htons(tpcb->local_port);
16066 }
16067 }
16068}
16069
16072}
16073
16074
16075#define MG_LWIP_IFACE_VTABLE \
16076 { \
16077 mg_lwip_if_init, \
16078 mg_lwip_if_free, \
16079 mg_lwip_if_add_conn, \
16080 mg_lwip_if_remove_conn, \
16081 mg_lwip_if_poll, \
16082 mg_lwip_if_listen_tcp, \
16083 mg_lwip_if_listen_udp, \
16084 mg_lwip_if_connect_tcp, \
16085 mg_lwip_if_connect_udp, \
16086 mg_lwip_if_tcp_send, \
16087 mg_lwip_if_udp_send, \
16088 mg_lwip_if_tcp_recv, \
16089 mg_lwip_if_udp_recv, \
16090 mg_lwip_if_create_conn, \
16091 mg_lwip_if_destroy_conn, \
16092 mg_lwip_if_sock_set, \
16093 mg_lwip_if_get_conn_addr, \
16094 }
16095
16096
16098#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
16100#endif
16101
16102#endif
16103#ifdef MG_MODULE_LINES
16104#line 1 "common/platforms/lwip/mg_lwip_ev_mgr.c"
16105#endif
16106
16107
16108
16109
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119
16120
16121
16122
16123#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
16124
16125#ifndef MG_SIG_QUEUE_LEN
16126#define MG_SIG_QUEUE_LEN 32
16127#endif
16128
16132};
16133
16138};
16139
16146 return;
16147 }
16149 md->sig_queue[end_index].sig = sig;
16150 md->sig_queue[end_index].nc = nc;
16151 md->sig_queue_len++;
16154}
16155
16159 while (md->sig_queue_len > 0) {
16161 int i = md->start_index;
16162 int sig = md->sig_queue[
i].sig;
16166 md->sig_queue_len--;
16169 switch (sig) {
16172 break;
16173 }
16176 break;
16177 }
16182 break;
16183 }
16185 break;
16186 }
16189 break;
16190 }
16191 }
16192 }
16193}
16194
16197 LWIP_VERSION_MINOR, LWIP_VERSION_REVISION));
16199#if !NO_SYS && !LWIP_TCPIP_CORE_LOCKING
16202#endif
16203}
16204
16207 iface->
data = NULL;
16208}
16209
16212}
16213
16217
16219 if (md->sig_queue[
i].nc == nc) {
16221 }
16222 }
16223}
16224
16230 double min_timer = 0;
16231 int num_timers = 0;
16232#if 0
16233 DBG((
"begin poll @%u", (
unsigned int) (now * 1000)));
16234#endif
16243 cs->
pcb.
tcp->unsent != NULL) {
16245 }
16249 }
16250 num_timers++;
16251 }
16252
16257 }
16261
16262
16263
16264
16266 }
16267 }
16268 }
16269#if 0
16270 DBG((
"end poll @%u, %d conns, %d timers (min %u), next in %d ms",
16271 (
unsigned int) (now * 1000),
n, num_timers,
16272 (unsigned int) (min_timer * 1000), timeout_ms));
16273#endif
16274 (void) timeout_ms;
16275 return now;
16276}
16277
16278#endif
16279#ifdef MG_MODULE_LINES
16280#line 1 "common/platforms/wince/wince_libc.c"
16281#endif
16282
16283
16284
16285
16286
16287
16288
16289
16290
16291
16292
16293
16294
16295
16296
16297
16298
16299#ifdef WINCE
16300
16301const char *strerror(
int err) {
16302
16303
16304
16305
16306 static char buf[10];
16307 snprintf(buf,
sizeof(buf),
"%d",
err);
16308 return buf;
16309}
16310
16311int open(const char *filename, int oflag, int pmode) {
16312
16313
16314
16315
16316
16317 DebugBreak();
16318 return 0;
16319}
16320
16321int _wstati64(const wchar_t *path, cs_stat_t *st) {
16322 DWORD fa = GetFileAttributesW(path);
16323 if (fa == INVALID_FILE_ATTRIBUTES) {
16324 return -1;
16325 }
16326 memset(st, 0, sizeof(*st));
16327 if ((fa & FILE_ATTRIBUTE_DIRECTORY) == 0) {
16328 HANDLE h;
16329 FILETIME ftime;
16330 st->st_mode |= _S_IFREG;
16331 h = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING,
16332 FILE_ATTRIBUTE_NORMAL, NULL);
16333 if (h == INVALID_HANDLE_VALUE) {
16334 return -1;
16335 }
16336 st->st_size = GetFileSize(h, NULL);
16337 GetFileTime(h, NULL, NULL, &ftime);
16338 st->st_mtime = (uint32_t)((((uint64_t) ftime.dwLowDateTime +
16339 ((uint64_t) ftime.dwHighDateTime << 32)) /
16340 10000000.0) -
16341 11644473600);
16342 CloseHandle(h);
16343 } else {
16344 st->st_mode |= _S_IFDIR;
16345 }
16346 return 0;
16347}
16348
16349
16351 FILETIME ft;
16352 SYSTEMTIME systime;
16353 if (t != NULL) {
16354 uint64_t filetime = (*t + 11644473600) * 10000000;
16355 ft.dwLowDateTime = filetime & 0xFFFFFFFF;
16356 ft.dwHighDateTime = (filetime & 0xFFFFFFFF00000000) >> 32;
16357 FileTimeToSystemTime(&ft, &systime);
16358 } else {
16359 GetSystemTime(&systime);
16360 }
16361
16362 snprintf(buf, buf_len, "%d.%d.%d %d:%d:%d GMT", (int) systime.wYear,
16363 (int) systime.wMonth, (int) systime.wDay, (int) systime.wHour,
16364 (int) systime.wMinute, (int) systime.wSecond);
16365}
16366
16367#endif
16368#ifdef MG_MODULE_LINES
16369#line 1 "common/platforms/pic32/pic32_net_if.h"
16370#endif
16371
16372
16373
16374
16375
16376
16377
16378
16379
16380
16381
16382
16383
16384
16385
16386
16387
16388#ifndef CS_COMMON_PLATFORMS_PIC32_NET_IF_H_
16389#define CS_COMMON_PLATFORMS_PIC32_NET_IF_H_
16390
16391
16392
16393#ifdef __cplusplus
16394extern "C" {
16395#endif
16396
16397#ifndef MG_ENABLE_NET_IF_PIC32
16398#define MG_ENABLE_NET_IF_PIC32 MG_NET_IF == MG_NET_IF_PIC32
16399#endif
16400
16402
16403#ifdef __cplusplus
16404}
16405#endif
16406
16407#endif
16408#ifdef MG_MODULE_LINES
16409#line 1 "common/platforms/pic32/pic32_net_if.c"
16410#endif
16411
16412
16413
16414
16415
16416
16417
16418
16419
16420
16421
16422
16423
16424
16425
16426
16427
16428#if MG_ENABLE_NET_IF_PIC32
16429
16431 (void) nc;
16432 return 1;
16433}
16434
16436 (void) nc;
16437 (void) len;
16438}
16439
16441 (void) nc;
16442}
16443
16445 (void) iface;
16447}
16448
16450 (void) iface;
16451}
16452
16454 (void) nc;
16455}
16456
16459
16461
16462 TCPIP_TCP_Close((TCP_SOCKET) nc->
sock);
16463 }
else if (nc->
listener == NULL) {
16464
16465 TCPIP_UDP_Close((UDP_SOCKET) nc->
sock);
16466 }
16467
16469}
16470
16472 nc->
sock = TCPIP_UDP_ServerOpen(
16473 sa->
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16474 : IP_ADDRESS_TYPE_IPV6,
16475 ntohs(sa->sin.sin_port),
16476 sa->sin.sin_addr.s_addr == 0 ? 0 : (IP_MULTI_ADDRESS *) &sa->sin);
16478 return -1;
16479 }
16480 return 0;
16481}
16482
16484 size_t len) {
16486}
16487
16489 size_t len) {
16491}
16492
16494 nc->
sock = TCPIP_TCP_ServerOpen(
16495 sa->
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16496 : IP_ADDRESS_TYPE_IPV6,
16497 ntohs(sa->sin.sin_port),
16498 sa->sin.sin_addr.s_addr == 0 ? 0 : (IP_MULTI_ADDRESS *) &sa->sin);
16499 memcpy(&nc->
sa, sa,
sizeof(*sa));
16501 return -1;
16502 }
16503 return 0;
16504}
16505
16508 TCP_SOCKET_INFO si;
16510
16512
16513 if (nc == NULL) {
16514 return 0;
16515 }
16516
16518 nc->
flags &= ~MG_F_LISTENING;
16519
16520 if (!TCPIP_TCP_SocketInfoGet((TCP_SOCKET) nc->
sock, &si)) {
16521 return 0;
16522 }
16523
16524 if (si.addressType == IP_ADDRESS_TYPE_IPV4) {
16525 sa.sin.sin_family = AF_INET;
16526 sa.sin.sin_port = htons(si.remotePort);
16527 sa.sin.sin_addr.s_addr = si.remoteIPaddress.v4Add.Val;
16528 } else {
16529
16530 memset(&
sa, 0,
sizeof(
sa));
16531 }
16532
16534
16536}
16537
16539 static char addr[17];
16540 snprintf(
addr,
sizeof(
addr),
"%d.%d.%d.%d", (
int) in.S_un.S_un_b.s_b1,
16541 (int) in.S_un.S_un_b.s_b2, (int) in.S_un.S_un_b.s_b3,
16542 (int) in.S_un.S_un_b.s_b4);
16544}
16545
16547 uint16_t bytes_written = 0;
16549 if (!TCPIP_UDP_RemoteBind(
16550 (UDP_SOCKET) nc->
sock,
16551 nc->
sa.
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16552 : IP_ADDRESS_TYPE_IPV6,
16553 ntohs(nc->
sa.
sin.sin_port), (IP_MULTI_ADDRESS *) &nc->
sa.
sin)) {
16555 return;
16556 }
16557 bytes_written = TCPIP_UDP_TxPutIsReady((UDP_SOCKET) nc->
sock, 0);
16559 if (TCPIP_UDP_ArrayPut((UDP_SOCKET) nc->
sock,
16563 bytes_written = 0;
16564 }
16565 }
16566 } else {
16567 bytes_written = TCPIP_TCP_FifoTxFreeGet((TCP_SOCKET) nc->
sock);
16568 if (bytes_written != 0) {
16571 }
16572 if (TCPIP_TCP_ArrayPut((TCP_SOCKET) nc->
sock,
16574 bytes_written) != bytes_written) {
16576 bytes_written = 0;
16577 }
16578 }
16579 }
16580
16582}
16583
16585 uint16_t bytes_read = 0;
16586 uint8_t *buf = NULL;
16588 bytes_read = TCPIP_UDP_GetIsReady((UDP_SOCKET) nc->
sock);
16589 if (bytes_read != 0 &&
16591 nc->
recv_mbuf.
len + bytes_read < nc->recv_mbuf_limit)) {
16592 buf = (uint8_t *)
MG_MALLOC(bytes_read);
16593 if (TCPIP_UDP_ArrayGet((UDP_SOCKET) nc->
sock, buf, bytes_read) !=
16594 bytes_read) {
16596 bytes_read = 0;
16598 }
16599 }
16600 } else {
16601 bytes_read = TCPIP_TCP_GetIsReady((TCP_SOCKET) nc->
sock);
16602 if (bytes_read != 0) {
16606 }
16607 buf = (uint8_t *)
MG_MALLOC(bytes_read);
16608 if (TCPIP_TCP_ArrayGet((TCP_SOCKET) nc->
sock, buf, bytes_read) !=
16609 bytes_read) {
16612 bytes_read = 0;
16613 }
16614 }
16615 }
16616
16617 if (bytes_read != 0) {
16619 }
16620}
16621
16626
16629
16631
16633 TCPIP_TCP_IsConnected((TCP_SOCKET) nc->
sock)) {
16635 }
16637 if (TCPIP_TCP_IsConnected((TCP_SOCKET) nc->
sock)) {
16638
16640 }
16641 } else {
16644 }
16645
16649 }
16650 }
16651 }
16652
16658 }
16659 }
16660
16661 return now;
16662}
16663
16666}
16667
16670
16671}
16672
16675 nc->
sock = TCPIP_TCP_ClientOpen(
16676 sa->
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16677 : IP_ADDRESS_TYPE_IPV6,
16678 ntohs(
sa->sin.sin_port), (IP_MULTI_ADDRESS *) &
sa->sin);
16680}
16681
16683 nc->
sock = TCPIP_UDP_ClientOpen(IP_ADDRESS_TYPE_ANY, 0, NULL);
16685}
16686
16687
16688#define MG_PIC32_IFACE_VTABLE \
16689 { \
16690 mg_pic32_if_init, \
16691 mg_pic32_if_free, \
16692 mg_pic32_if_add_conn, \
16693 mg_pic32_if_remove_conn, \
16694 mg_pic32_if_poll, \
16695 mg_pic32_if_listen_tcp, \
16696 mg_pic32_if_listen_udp, \
16697 mg_pic32_if_connect_tcp, \
16698 mg_pic32_if_connect_udp, \
16699 mg_pic32_if_tcp_send, \
16700 mg_pic32_if_udp_send, \
16701 mg_pic32_if_recved, \
16702 mg_pic32_if_create_conn, \
16703 mg_pic32_if_destroy_conn, \
16704 mg_pic32_if_sock_set, \
16705 mg_pic32_if_get_conn_addr, \
16706 }
16707
16708
16710#if MG_NET_IF == MG_NET_IF_PIC32
16712#endif
16713
16714#endif
16715#ifdef MG_MODULE_LINES
16716#line 1 "common/platforms/windows/windows_direct.c"
16717#endif
16718
16719
16720
16721
16722
16723
16724
16725
16726
16727
16728
16729
16730
16731
16732
16733
16734
16735#ifdef _WIN32
16736
16737int rmdir(
const char *dirname) {
16738 return _rmdir(dirname);
16739}
16740
16741unsigned int sleep(
unsigned int seconds) {
16742 Sleep(seconds * 1000);
16743 return 0;
16744}
16745
16746#endif
int mg_start_thread(mg_thread_func_t f, void *p)
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
int(* mg_event_handler_t)(struct mg_event *event)
int mg_mgr_poll(struct mg_mgr *m, int timeout_ms)
void mg_mqtt_ping(struct mg_connection *nc)
void mg_set_protocol_mqtt(struct mg_connection *nc)
void mg_mgr_free(struct mg_mgr *m)
const char * hexdump_file
int mg_resolve_from_hosts_file(const char *host, union socket_address *usa)
void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len)
void cs_to_hex(char *to, const unsigned char *p, size_t len) WEAK
#define WEBSOCKET_DONT_FIN
#define MG_MK_STR(str_literal)
void mg_send_dns_query(struct mg_connection *nc, const char *name, int query_type)
#define WEBSOCKET_OP_PING
char * cs_md5(char buf[33],...)
void mg_mqtt_disconnect(struct mg_connection *nc)
#define MG_MQTT_HAS_USER_NAME
#define MG_MQTT_CMD_PUBREC
void mg_mqtt_publish(struct mg_connection *nc, const char *topic, uint16_t message_id, int flags, const void *data, size_t len)
void mg_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
#define MG_MQTT_CMD_UNSUBACK
struct mg_str header_names[MG_MAX_HTTP_HEADERS]
int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap) WEAK
#define MG_MAX_HTTP_HEADERS
#define MG_MAX_HTTP_SEND_MBUF
#define MG_MAX_DNS_ANSWERS
#define MG_EV_WEBSOCKET_FRAME
int mg_stat(const char *path, cs_stat_t *st)
struct mg_connection * mg_connect_http(struct mg_mgr *mgr, mg_event_handler_t event_handler, const char *url, const char *extra_headers, const char *post_data)
const char * global_auth_file
#define MG_EV_WEBSOCKET_HANDSHAKE_DONE
int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query, mg_resolve_callback_t cb, void *data, struct mg_resolve_async_opts opts)
mg_event_handler_t handler
struct mg_connection * active_connections
void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code)
#define MG_MQTT_CMD_PUBACK
int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr, const char *name, size_t nlen, const void *rdata, size_t rlen)
void mg_mqtt_pong(struct mg_connection *nc)
struct mg_connection ** dns_conn
int mg_is_big_endian(void)
#define MG_F_CLOSE_IMMEDIATELY
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t) WEAK
size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name, size_t var_name_len, char *file_name, size_t file_name_len, const char **chunk, size_t *chunk_len)
#define MG_SOCK_STRINGIFY_PORT
void mbuf_remove(struct mbuf *mb, size_t n) WEAK
void mg_mgr_init(struct mg_mgr *m, void *user_data)
int mg_dns_insert_header(struct mbuf *io, size_t pos, struct mg_dns_message *msg)
const char * extra_headers
void mg_send_head(struct mg_connection *n, int status_code, int64_t content_length, const char *extra_headers)
void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id)
void(* proto_data_destructor)(void *proto_data)
struct mg_connection * mg_next(struct mg_mgr *s, struct mg_connection *conn)
int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query, mg_resolve_callback_t cb, void *data)
void mg_if_accept_tcp_cb(struct mg_connection *nc, union socket_address *sa, size_t sa_len)
int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out)
#define WEBSOCKET_OP_CLOSE
const char * c_strnstr(const char *s, const char *find, size_t slen) WEAK
int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap)
const char * mg_set_ssl(struct mg_connection *nc, const char *cert, const char *ca_cert)
void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t)
#define MG_DNS_AAAA_RECORD
void mg_send_response_line(struct mg_connection *c, int status_code, const char *extra_headers)
#define MG_MQTT_CMD_CONNACK
void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id)
#define MG_VPRINTF_BUFFER_SIZE
struct mg_str header_values[MG_MAX_HTTP_HEADERS]
void mbuf_free(struct mbuf *mbuf) WEAK
const char * url_rewrites
#define MG_EV_WEBSOCKET_CONTROL_FRAME
void mg_serve_http(struct mg_connection *nc, struct http_message *hm, struct mg_serve_http_opts opts)
const char ** error_string
#define MG_MAX_CGI_ENVIR_VARS
#define MG_SOCK_STRINGIFY_REMOTE
int mg_open(const char *path, int flag, int mode)
double mg_set_timer(struct mg_connection *c, double timestamp)
int mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len, int flags)
#define MG_MQTT_GET_QOS(flags)
int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req)
size_t mg_match_prefix_n(const struct mg_str, const struct mg_str) WEAK
#define MG_SEND_FUNC(s, b, l, f)
void mbuf_resize(struct mbuf *a, size_t new_size) WEAK
void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len)
void mg_printf_html_escape(struct mg_connection *nc, const char *fmt,...)
void mg_if_sent_cb(struct mg_connection *nc, int num_sent)
#define MG_DNS_CNAME_RECORD
struct mg_connection * mg_if_accept_new_conn(struct mg_connection *lc)
#define MG_CGI_ENVIRONMENT_SIZE
const char * cgi_file_pattern
int mg_casecmp(const char *s1, const char *s2) WEAK
void mg_send(struct mg_connection *nc, const void *buf, int len)
int mg_socketpair(sock_t[2], int sock_type)
#define WEBSOCKET_OP_PONG
#define MG_MQTT_CMD_PUBREL
struct mg_connection * next
void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len)
#define MG_MQTT_CMD_PINGREQ
const char * cgi_interpreter
#define MG_EV_MQTT_CONNACK_SERVER_UNAVAILABLE
#define MG_ENV_EXPORT_TO_CGI
void mg_hexdump_connection(struct mg_connection *nc, const char *path, const void *buf, int num_bytes, int ev)
enum mg_dns_resource_record_kind kind
#define ARRAY_SIZE(array)
void mg_if_connect_cb(struct mg_connection *nc, int err)
int mg_http_create_digest_auth_header(char *buf, size_t buf_len, const char *method, const char *uri, const char *auth_domain, const char *user, const char *passwd)
#define MG_EV_MQTT_CONNECT
void mg_sock_set(struct mg_connection *nc, sock_t sock)
void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path, const char *host, const char *protocol, const char *extra_headers)
void cs_base64_finish(struct cs_base64_ctx *ctx)
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, mg_event_handler_t handler)
void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags)
#define MG_MQTT_CMD_PUBCOMP
void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id)
struct mg_str query_string
void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags, const char *fmt,...)
#define MG_MQTT_EVENT_BASE
#define MG_MQTT_CMD_PUBLISH
struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS]
#define MG_SOCK_STRINGIFY_IP
const char * enable_directory_listing
size_t mg_match_prefix(const char *, int, const char *) WEAK
#define MG_MQTT_CMD_PINGRESP
#define MG_MQTT_CMD_CONNECT
const char * dav_auth_file
void mg_set_protocol_http_websocket(struct mg_connection *nc)
void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags, const struct mg_str *strings, int num_strings)
int mg_hexdump(const void *buf, int len, char *dst, int dst_len)
int mg_vcasecmp(const struct mg_str *str1, const char *str2) WEAK
#define MG_WEBSOCKET_PING_INTERVAL_SECONDS
int mg_base64_decode(const unsigned char *s, int len, char *dst)
struct mg_connection * mg_connect_ws(struct mg_mgr *mgr, mg_event_handler_t event_handler, const char *url, const char *protocol, const char *extra_headers)
struct mg_connection * listener
struct mg_connection * prev
#define MG_MQTT_HAS_PASSWORD
void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id)
void mg_set_close_on_exec(sock_t sock)
double cs_time(void) WEAK
struct mg_connection * mg_connect_ws_opt(struct mg_mgr *mgr, mg_event_handler_t ev_handler, struct mg_connect_opts opts, const char *url, const char *protocol, const char *extra_headers)
#define MG_F_DELETE_CHUNK
int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len)
void mg_set_protocol_dns(struct mg_connection *nc)
const char * mg_skip(const char *s, const char *end, const char *delims, struct mg_str *v)
void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len, uint16_t message_id)
#define MG_MAX_HTTP_REQUEST_SIZE
#define MG_MQTT_CMD_UNSUBSCRIBE
int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg)
const char * hidden_file_pattern
void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id)
void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc, void *user_data)
struct mg_dns_resource_record * mg_dns_next_record(struct mg_dns_message *msg, int query, struct mg_dns_resource_record *prev)
const char * document_root
void mbuf_init(struct mbuf *mbuf, size_t initial_size) WEAK
void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id, struct mg_send_mqtt_handshake_opts)
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) WEAK
#define MG_F_SSL_HANDSHAKE_DONE
int mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len, int flags)
const char * per_directory_auth_file
void mg_base64_encode(const unsigned char *src, int src_len, char *dst)
void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags, const void *data, size_t data_len)
#define MG_EV_MQTT_PUBLISH
void(* mg_resolve_callback_t)(struct mg_dns_message *dns_message, void *user_data, enum mg_resolve_err)
#define MG_F_IS_WEBSOCKET
#define MG_RECV_FUNC(s, b, l, f)
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context)
const char ** error_string
int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf, size_t buf_size)
struct mg_str mg_mk_str(const char *s) WEAK
const char ** error_string
void cs_base64_encode(const unsigned char *src, int src_len, char *dst)
int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst, size_t dst_len)
void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri, const char *extra_headers)
void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt,...)
#define MG_EV_MQTT_SUBSCRIBE
const char * mg_next_comma_list_entry(const char *, struct mg_str *, struct mg_str *) WEAK
size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name, char *dst, int dst_len)
struct mg_connection * mg_connect_http_opt(struct mg_mgr *mgr, mg_event_handler_t ev_handler, struct mg_connect_opts opts, const char *url, const char *extra_headers, const char *post_data)
void mbuf_trim(struct mbuf *mbuf) WEAK
#define MG_MQTT_CMD_DISCONNECT
FILE * mg_fopen(const char *path, const char *mode)
struct mg_str * mg_get_http_header(struct http_message *hm, const char *name)
void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data, uint32_t len)
#define MG_MQTT_CMD_SUBSCRIBE
#define MG_MQTT_CMD_SUBACK
int mg_vcmp(const struct mg_str *str1, const char *str2) WEAK
int mg_parse_uri(const struct mg_str uri, struct mg_str *scheme, struct mg_str *user_info, struct mg_str *host, unsigned int *port, struct mg_str *path, struct mg_str *query, struct mg_str *fragment)
int mg_check_ip_acl(const char *acl, uint32_t remote_ip)
struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS]
mg_event_handler_t proto_handler
const char * dav_document_root
MG_INTERNAL void mg_close_conn(struct mg_connection *conn)
struct mg_str resp_status_msg
void cs_sha1_init(cs_sha1_ctx *context)
int mg_ncasecmp(const char *s1, const char *s2, size_t len) WEAK
int mg_dns_parse_record_data(struct mg_dns_message *msg, struct mg_dns_resource_record *rr, void *data, size_t data_len)
#define MG_EV_MQTT_CONNACK_ACCEPTED
void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics, size_t topics_len, uint16_t message_id)
#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST
int mg_printf(struct mg_connection *conn, const char *fmt,...)
void mg_mqtt_subscribe(struct mg_connection *nc, const struct mg_mqtt_topic_expression *topics, size_t topics_len, uint16_t message_id)
void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id)
#define WEBSOCKET_OP_CONTINUE
int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg, struct mg_str *topic, uint8_t *qos, int pos)
#define MG_F_SEND_AND_CLOSE
#define MG_EV_HTTP_REQUEST
@ MG_RESOLVE_EXCEEDED_RETRY_COUNT
static std::string q(const char *s)
#define message(type, str)
#define write(n, a, f, d)
static void do_ssi_exec(struct mg_connection *conn, char *tag)
static const char * month_names[]
void mg_set_nameserver(struct mg_mgr *mgr, const char *nameserver)
#define MG_AUTH_FLAG_IS_GLOBAL_PASS_FILE
#define DO_NOT_WARN_UNUSED
void mg_http_send_error(struct mg_connection *nc, int code, const char *reason)
int mg_get_http_basic_auth(struct http_message *hm, char *user, size_t user_len, char *pass, size_t pass_len)
int mg_parse_http_basic_auth(struct mg_str *hdr, char *user, size_t user_len, char *pass, size_t pass_len)
#define MG_AUTH_FLAG_IS_DIRECTORY
void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[], const size_t *msg_lens, uint8_t *digest)
void mg_send_websocket_handshake3v(struct mg_connection *nc, const struct mg_str path, const struct mg_str host, const struct mg_str protocol, const struct mg_str extra_headers, const struct mg_str user, const struct mg_str pass)
#define MG_ENABLE_HTTP_WEBDAV
#define LIST_REMOVE(elm, field)
#define MG_EV_SSI_CALL_CTX
void mg_http_send_digest_auth_request(struct mg_connection *c, const char *domain)
#define MG_AUTH_FLAG_ALLOW_MISSING_FILE
#define MG_F_RECV_AND_CLOSE
void mg_http_send_redirect(struct mg_connection *nc, int status_code, const struct mg_str location, const struct mg_str extra_headers)
int mg_check_digest_auth(struct mg_str method, struct mg_str uri, struct mg_str username, struct mg_str cnonce, struct mg_str response, struct mg_str qop, struct mg_str nc, struct mg_str nonce, struct mg_str auth_domain, FILE *fp)
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic)
int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain, FILE *fp)
int mg_http_parse_header2(struct mg_str *hdr, const char *var_name, char **buf, size_t buf_size)
void mg_hash_md5_v(size_t num_msgs, const uint8_t *msgs[], const size_t *msg_lens, uint8_t *digest)
int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len)
#define MG_ENABLE_HTTP_STREAMING_MULTIPART
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic)
#define LIST_NEXT(elm, field)
void mg_send_websocket_handshake3(struct mg_connection *nc, const char *path, const char *host, const char *protocol, const char *extra_headers, const char *user, const char *pass)
#define LIST_INSERT_HEAD(head, elm, field)
int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg)
int mg_http_is_authorized(struct http_message *hm, struct mg_str path, const char *domain, const char *passwords_file, int flags)
void mg_register_http_endpoint_opt(struct mg_connection *nc, const char *uri_path, mg_event_handler_t handler, struct mg_http_endpoint_opts opts)
#define MG_COPY_COMMON_CONNECTION_OPTIONS(dst, src)
int mg_pic32_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
void mg_pic32_if_udp_send(struct mg_connection *nc, const void *buf, size_t len)
void mg_socket_if_sock_set(struct mg_connection *nc, sock_t sock)
int _kill(int pid, int sig)
void cs_md5_final(unsigned char digest[16], cs_md5_ctx *ctx)
void mg_lwip_if_connect_udp(struct mg_connection *nc)
struct mg_connection * mg_bind(struct mg_mgr *srv, const char *address, MG_CB(mg_event_handler_t event_handler, void *user_data))
int mg_pic32_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
static int mg_accept_conn(struct mg_connection *lc)
static int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
void mg_socket_if_connect_udp(struct mg_connection *nc)
void mg_sl_if_sock_set(struct mg_connection *nc, sock_t sock)
static sock_t mg_open_listening_socket(union socket_address *sa, int type, int proto)
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) WEAK
MG_INTERNAL void mg_remove_conn(struct mg_connection *c)
void sl_restart_cb(struct mg_mgr *mgr)
void cs_md5_init(cs_md5_ctx *ctx)
struct mg_connection * mg_add_sock_opt(struct mg_mgr *s, sock_t sock, MG_CB(mg_event_handler_t callback, void *user_data), struct mg_add_sock_opts opts)
static int mg_sl_if_udp_recv(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
const struct mg_iface_vtable * mg_ifaces[]
static void mg_lwip_if_connect_tcp_tcpip(void *arg)
MG_INTERNAL struct mg_connection * mg_create_connection_base(struct mg_mgr *mgr, mg_event_handler_t callback, struct mg_add_sock_opts opts)
static int mg_socket_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
#define MG_LWIP_IFACE_VTABLE
static int mg_do_recv(struct mg_connection *nc)
MG_INTERNAL struct mg_connection * mg_create_connection(struct mg_mgr *mgr, mg_event_handler_t callback, struct mg_add_sock_opts opts)
void mg_lwip_if_destroy_conn(struct mg_connection *nc)
static int mg_socket_if_udp_recv(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
void mg_pic32_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
time_t mg_pic32_if_poll(struct mg_iface *iface, int timeout_ms)
static void mg_null_if_add_conn(struct mg_connection *c)
int mg_null_if_tcp_recv(struct mg_connection *c, void *buf, size_t len)
void mg_lwip_if_add_conn(struct mg_connection *nc)
static void mg_lwip_tcp_error_cb(void *arg, err_t err)
void mg_mbuf_append_base64_putc(char ch, void *user_data)
#define _MG_CALLBACK_MODIFIABLE_FLAGS_MASK
void mg_basic_auth_header(const struct mg_str user, const struct mg_str pass, struct mbuf *buf)
static void tcp_output_tcpip(void *arg)
bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init)
double mg_mgr_min_timer(const struct mg_mgr *mgr)
static void mg_lwip_if_connect_udp_tcpip(void *arg)
static void mg_null_if_get_conn_addr(struct mg_connection *c, int remote, union socket_address *sa)
#define MG_UDP_RECV_BUFFER_SIZE
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
int mg_lwip_if_create_conn(struct mg_connection *nc)
time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms)
void mg_pic32_if_recved(struct mg_connection *nc, size_t len)
static void mg_null_if_free(struct mg_iface *iface)
void mg_pic32_if_add_conn(struct mg_connection *nc)
void mg_lwip_handle_accept(struct mg_connection *nc)
struct mg_str mg_url_encode(const struct mg_str src)
static int mg_sl_if_create_conn(struct mg_connection *nc)
int mg_asprintf(char **buf, size_t size, const char *fmt,...) WEAK
MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max)
static void mg_sl_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
void mg_lwip_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
void _not_implemented(const char *what)
static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t num_sent)
void mg_lwip_if_free(struct mg_iface *iface)
struct mg_str mg_url_encode_opt(const struct mg_str src, const struct mg_str safe, unsigned int flags)
int mg_strncmp(const struct mg_str, const struct mg_str, size_t n) WEAK
int mg_if_poll(struct mg_connection *nc, double now)
static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err)
static int mg_lwip_if_can_send(struct mg_connection *nc, struct mg_lwip_conn_state *cs)
void mg_socket_if_add_conn(struct mg_connection *nc)
void mg_sl_if_add_conn(struct mg_connection *nc)
void mg_sl_if_remove_conn(struct mg_connection *nc)
static void mg_handle_recv(struct mg_connection *nc)
static err_t mg_lwip_tcp_conn_cb(void *arg, struct tcp_pcb *tpcb, err_t err)
static int mg_lwip_if_udp_send(struct mg_connection *nc, const void *data, size_t len)
void mg_lwip_if_remove_conn(struct mg_connection *nc)
void mg_socket_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
static time_t mg_null_if_poll(struct mg_iface *iface, int timeout_ms)
void mg_mgr_init_opt(struct mg_mgr *m, void *user_data, struct mg_mgr_init_opts opts)
static void udp_sendto_tcpip(void *arg)
void mg_socket_if_init(struct mg_iface *iface)
struct mg_connection * mg_connect(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data))
#define MG_PIC32_IFACE_VTABLE
#define _MG_ALLOWED_CONNECT_FLAGS_MASK
static int mg_recv_tcp(struct mg_connection *nc, char *buf, size_t len)
void mg_pic32_if_init(struct mg_iface *iface)
static void mg_null_if_init(struct mg_iface *iface)
static void mg_null_if_destroy_conn(struct mg_connection *c)
struct mg_str mg_strdup(const struct mg_str s) WEAK
static int mg_null_if_create_conn(struct mg_connection *c)
void mg_set_non_blocking_mode(sock_t sock)
static void mg_null_if_sock_set(struct mg_connection *c, sock_t sock)
void mg_socket_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
void mg_socket_if_remove_conn(struct mg_connection *nc)
void mg_pic32_if_connect_udp(struct mg_connection *nc)
void mg_lwip_if_init(struct mg_iface *iface)
const struct mg_iface_vtable mg_default_iface_vtable
void mg_pic32_if_free(struct mg_iface *iface)
static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p)
void mg_if_can_recv_cb(struct mg_connection *nc)
static int mg_lwip_if_udp_recv(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
static int mg_socket_if_udp_send(struct mg_connection *nc, const void *buf, size_t len)
static void mg_sock_get_addr(sock_t sock, int remote, union socket_address *sa)
MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa, int *proto, char *host, size_t host_len)
static int mg_sl_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr)
void mg_mbuf_append_base64(struct mbuf *mbuf, const void *data, size_t len)
void mg_lwip_netif_run_on_tcpip(void(*fn)(void *), void *arg)
#define _MG_F_FD_CAN_READ
#define MG_SL_IFACE_VTABLE
static void mg_null_if_connect_udp(struct mg_connection *c)
static void mg_sl_if_connect_udp(struct mg_connection *nc)
static int mg_sl_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len)
static void parse_uri_component(const char **p, const char *end, const char *seps, struct mg_str *res)
#define MG_SET_PTRPTR(_ptr, _v)
int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len)
static void tcp_close_tcpip(void *arg)
const struct mg_iface_vtable mg_simplelink_iface_vtable
static int mg_null_if_listen_tcp(struct mg_connection *c, union socket_address *sa)
int mg_assemble_uri(const struct mg_str *scheme, const struct mg_str *user_info, const struct mg_str *host, unsigned int port, const struct mg_str *path, const struct mg_str *query, const struct mg_str *fragment, int normalize_path, struct mg_str *uri)
void mg_pic32_if_destroy_conn(struct mg_connection *nc)
void mg_lwip_if_sock_set(struct mg_connection *nc, sock_t sock)
struct mg_iface * mg_if_create_iface(const struct mg_iface_vtable *vtable, struct mg_mgr *mgr)
static sys_sem_t s_tcpip_call_lock_sem
static int mg_socket_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
struct mg_connection * mg_bind_opt(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data), struct mg_bind_opts opts)
const char * mg_strstr(const struct mg_str haystack, const struct mg_str needle) WEAK
void mg_lwip_post_signal(enum mg_sig_type sig, struct mg_connection *nc)
const struct mg_iface_vtable mg_pic32_iface_vtable
static int mg_socket_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len)
static sys_sem_t s_tcpip_call_sync_sem
static void mg_lwip_tcp_write_tcpip(void *arg)
char * inet_ntoa(struct in_addr n)
void mg_forward(struct mg_connection *from, struct mg_connection *to)
static int mg_null_if_tcp_send(struct mg_connection *c, const void *buf, size_t len)
static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len)
static int mg_null_if_udp_send(struct mg_connection *c, const void *buf, size_t len)
static void mg_task(void *arg)
void mg_sl_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
void mg_sl_if_destroy_conn(struct mg_connection *nc)
const char * mg_strchr(const struct mg_str s, int c) WEAK
static void mg_lwip_if_listen_tcp_tcpip(void *arg)
int mg_null_if_udp_recv(struct mg_connection *c, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
int mg_pic32_if_create_conn(struct mg_connection *nc)
void mg_pic32_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
struct mg_str mg_mk_str_n(const char *s, size_t len) WEAK
void mg_pic32_if_sock_set(struct mg_connection *nc, sock_t sock)
int mg_lwip_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
#define MG_SOCKET_IFACE_VTABLE
int mg_socket_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
void mg_sl_if_init(struct mg_iface *iface)
static void mg_null_if_remove_conn(struct mg_connection *c)
const struct mg_iface_vtable mg_socket_iface_vtable
const char * inet_ntop(int af, const void *src, char *dst, socklen_t size)
int gettimeofday(struct timeval *tp, void *tzp)
void cs_md5_update(cs_md5_ctx *ctx, const unsigned char *buf, size_t len)
struct mg_iface * mg_find_iface(struct mg_mgr *mgr, const struct mg_iface_vtable *vtable, struct mg_iface *from)
static void mg_handle_send(struct mg_connection *nc)
#define SET_ADDR(dst, src)
static void udp_remove_tcpip(void *arg)
static void mg_lwip_if_listen_udp_tcpip(void *arg)
void mg_sl_if_free(struct mg_iface *iface)
MG_INTERNAL void mg_add_conn(struct mg_mgr *mgr, struct mg_connection *c)
int inet_pton(int af, const char *src, void *dst)
int mg_lwip_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
#define _MG_F_FD_CAN_WRITE
static int mg_sl_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
MG_INTERNAL struct mg_connection * mg_do_connect(struct mg_connection *nc, int proto, union socket_address *sa)
void mg_ev_handler_empty(struct mg_connection *c, int ev, void *ev_data MG_UD_ARG(void *user_data))
void mg_socket_if_free(struct mg_iface *iface)
void mg_if_can_send_cb(struct mg_connection *nc)
static int mg_sl_if_udp_send(struct mg_connection *nc, const void *buf, size_t len)
static void mg_null_if_connect_tcp(struct mg_connection *c, const union socket_address *sa)
static void xxx_tcpip(void *arg)
void mg_pic32_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
void mg_lwip_mgr_schedule_poll(struct mg_mgr *mgr)
static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
void mg_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd)
const struct mg_iface_vtable mg_lwip_iface_vtable
void fprint_str(FILE *fp, const char *str)
struct mg_connection * mg_connect_opt(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data), struct mg_connect_opts opts)
int mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
void mg_destroy_conn(struct mg_connection *conn, int destroy_if)
void mg_lwip_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
time_t mg_sl_if_poll(struct mg_iface *iface, int timeout_ms)
MG_INTERNAL int mg_get_errno(void)
int mg_socket_if_create_conn(struct mg_connection *nc)
static int mg_is_error(void)
MG_INTERNAL void mg_call(struct mg_connection *nc, mg_event_handler_t ev_handler, void *user_data, int ev, void *ev_data)
static int mg_recv_udp(struct mg_connection *nc, char *buf, size_t len)
void mg_socket_if_destroy_conn(struct mg_connection *nc)
void mg_run_in_task(void(*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg)
static int mg_null_if_listen_udp(struct mg_connection *c, union socket_address *sa)
void mg_pic32_if_remove_conn(struct mg_connection *nc)
#define MG_NULL_IFACE_VTABLE
void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now)
time_t mg_socket_if_poll(struct mg_iface *iface, int timeout_ms)
struct mg_connection * mg_add_sock(struct mg_mgr *s, sock_t sock, MG_CB(mg_event_handler_t callback, void *user_data))
MG_INTERNAL void mg_timer(struct mg_connection *c, double now)
void tcp_recved_tcpip(void *arg)
struct mg_str mg_url_encode_opt(const struct mg_str src, const struct mg_str safe, unsigned int flags)
const char * mg_strchr(const struct mg_str s, int c)
struct mg_str mg_mk_str_n(const char *s, size_t len)
#define MG_URL_ENCODE_F_UPPERCASE_HEX
#define MG_URL_ENCODE_F_SPACE_AS_PLUS
static size_t mg_http_parse_chunk(char *buf, size_t len, char **chunk_data, size_t *chunk_len)
mg_http_multipart_stream_state
@ MPS_WAITING_FOR_BOUNDARY
MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm)
static void mg_send_directory_listing(struct mg_connection *nc, const char *dir, struct http_message *hm, struct mg_serve_http_opts *opts)
MG_INTERNAL int mg_uri_to_local_path(struct http_message *hm, const struct mg_serve_http_opts *opts, char **local_path, struct mg_str *remainder)
static void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d)
static void mqtt_handler(struct mg_connection *nc, int ev, void *ev_data)
static int mg_resolve2(const char *host, struct in_addr *ina)
static void mg_handle_cgi(struct mg_connection *nc, const char *prog, const struct mg_str *path_info, const struct http_message *hm, const struct mg_serve_http_opts *opts)
static struct mg_http_proto_data * mg_http_get_proto_data(struct mg_connection *c)
static void mg_send_file_data(struct mg_connection *nc, FILE *fp)
static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *data)
static const struct @23 mg_static_builtin_mime_types[]
#define MIME_ENTRY(_ext, _type)
static int mg_create_itermediate_directories(const char *path)
MG_INTERNAL void mg_send_http_file(struct mg_connection *nc, char *path, const struct mg_str *path_info, struct http_message *hm, struct mg_serve_http_opts *opts)
static void dns_handler(struct mg_connection *nc, int ev, void *ev_data)
static void mg_http_construct_etag(char *buf, size_t buf_len, const cs_stat_t *st)
MG_INTERNAL time_t mg_parse_date_string(const char *datetime)
static void resolve_cb(struct mg_dns_message *msg, void *data, enum mg_resolve_err e)
static mg_event_handler_t mg_http_get_endpoint_handler(struct mg_connection *nc, struct mg_str *uri_path)
static int mg_is_ws_first_fragment(unsigned char flags)
static int mg_remove_directory(const struct mg_serve_http_opts *opts, const char *dir)
static int mg_check_nonce(const char *nonce)
static void mg_scan_directory(struct mg_connection *nc, const char *dir, const struct mg_serve_http_opts *opts, void(*func)(struct mg_connection *, const char *, cs_stat_t *))
static void mg_print_dir_entry(struct mg_connection *nc, const char *file_name, cs_stat_t *stp)
struct mg_connection * mg_connect_http_base(struct mg_mgr *mgr, mg_event_handler_t ev_handler, struct mg_connect_opts opts, const char *schema, const char *schema_ssl, const char *url, const char **path, char **addr)
static int left(const struct frozen *f)
static void mg_handle_put(struct mg_connection *nc, const char *path, struct http_message *hm)
static const char * mg_http_parse_headers(const char *s, const char *end, int len, struct http_message *req)
static void mg_escape(const char *src, char *dst, size_t dst_len)
static void mg_send_ssi_file(struct mg_connection *, const char *, FILE *, int, const struct mg_serve_http_opts *)
MG_INTERNAL int mg_is_not_modified(struct http_message *hm, cs_stat_t *st)
static int mg_get_month_index(const char *s)
static uint32_t mg_ws_random_mask(void)
static void mg_http_free_proto_data_file(struct mg_http_proto_data_file *d)
static int mg_get_ip_address_of_nameserver(char *name, size_t name_len)
static int mg_is_dav_request(const struct mg_str *s)
static unsigned char * mg_parse_dns_resource_record(unsigned char *data, unsigned char *end, struct mg_dns_resource_record *rr, int reply)
static void mg_mgr_handle_ctl_sock(struct mg_mgr *mgr)
static char * mg_addenv(struct mg_cgi_env_block *block, const char *fmt,...)
static void mg_ws_mask_frame(struct mbuf *mbuf, struct ws_mask_ctx *ctx)
static void mg_prepare_cgi_environment(struct mg_connection *nc, const char *prog, const struct mg_str *path_info, const struct http_message *hm, const struct mg_serve_http_opts *opts, struct mg_cgi_env_block *blk)
static void mg_handle_incoming_websocket_frame(struct mg_connection *nc, struct websocket_message *wsm)
static int mg_is_file_hidden(const char *path, const struct mg_serve_http_opts *opts, int exclude_specials)
static void mg_handle_ssi_request(struct mg_connection *nc, const char *path, const struct mg_serve_http_opts *opts)
static int mg_http_get_request_len(const char *s, int buf_len)
MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc, struct http_message *hm, char *buf, size_t blen)
static void mg_addenv2(struct mg_cgi_env_block *blk, const char *name)
static void mg_send_ws_header(struct mg_connection *nc, int op, size_t len, struct ws_mask_ctx *ctx)
static int mg_http_parse_range_header(const struct mg_str *header, int64_t *a, int64_t *b)
static void mg_print_props(struct mg_connection *nc, const char *name, cs_stat_t *stp)
static pid_t mg_start_process(const char *interp, const char *cmd, const char *env, const char *envp[], const char *dir, sock_t sock)
static int mg_is_ws_fragment(unsigned char flags)
MG_INTERNAL void mg_find_index_file(const char *path, const char *list, char **index_file, cs_stat_t *stp)
static int mg_deliver_websocket_data(struct mg_connection *nc)
static void mg_http_free_proto_data_endpoints(struct mg_http_endpoint **ep)
static void mg_cgi_ev_handler(struct mg_connection *cgi_nc, int ev, void *ev_data)
static size_t mg_get_line_len(const char *buf, size_t buf_len)
static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev, struct http_message *hm)
static void mg_handle_mkcol(struct mg_connection *nc, const char *path, struct http_message *hm)
static void mg_http_transfer_file_data(struct mg_connection *nc)
static void mg_mkmd5resp(const char *method, size_t method_len, const char *uri, size_t uri_len, const char *ha1, size_t ha1_len, const char *nonce, size_t nonce_len, const char *nc, size_t nc_len, const char *cnonce, size_t cnonce_len, const char *qop, size_t qop_len, char *resp)
void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data)
static int mg_http_send_port_based_redirect(struct mg_connection *c, struct http_message *hm, const struct mg_serve_http_opts *opts)
static void mg_handle_delete(struct mg_connection *nc, const struct mg_serve_http_opts *opts, const char *path)
static void mg_handle_move(struct mg_connection *c, const struct mg_serve_http_opts *opts, const char *path, struct http_message *hm)
static void mg_handle_propfind(struct mg_connection *nc, const char *path, cs_stat_t *stp, struct http_message *hm, struct mg_serve_http_opts *opts)
static void mg_gmt_time_string(char *buf, size_t buf_len, time_t *t)
static void mg_http_send_options(struct mg_connection *nc)
#define MG_DEFAULT_NAMESERVER
static void mg_ws_handshake(struct mg_connection *nc, const struct mg_str *key)
static int mg_is_creation_request(const struct http_message *hm)
static int mg_num_leap_years(int year)
static struct mg_str mg_get_mime_type(const char *path, const char *dflt, const struct mg_serve_http_opts *opts)
static void mg_send_mqtt_short_command(struct mg_connection *nc, uint8_t cmd, uint16_t message_id)
struct callback_addr callback
char message[MG_CTL_MSG_MESSAGE_SIZE]
mg_event_handler_t callback
const char * vars[MG_MAX_CGI_ENVIR_VARS]
struct mg_connection * nc
char buf[MG_CGI_ENVIRONMENT_SIZE]
struct mg_ev_mgr_lwip_signal sig_queue[MG_SIG_QUEUE_LEN]
struct mg_connection * nc
mg_event_handler_t handler
struct mg_http_endpoint * next
enum mg_http_multipart_stream_state state
struct mg_connection * cgi_nc
enum mg_http_proto_data_type type
struct mg_http_proto_data_chuncked chunk
struct mg_http_endpoint * endpoints
struct mg_http_proto_data_cgi cgi
mg_event_handler_t endpoint_handler
struct mg_http_proto_data_file file
time_t(* poll)(struct mg_iface *iface, int timeout_ms)
void(* destroy_conn)(struct mg_connection *nc)
int(* listen_tcp)(struct mg_connection *nc, union socket_address *sa)
void(* remove_conn)(struct mg_connection *nc)
void(* connect_tcp)(struct mg_connection *nc, const union socket_address *sa)
void(* free)(struct mg_iface *iface)
void(* init)(struct mg_iface *iface)
void(* get_conn_addr)(struct mg_connection *nc, int remote, union socket_address *sa)
void(* connect_udp)(struct mg_connection *nc)
int(* udp_send)(struct mg_connection *nc, const void *buf, size_t len)
int(* create_conn)(struct mg_connection *nc)
int(* listen_udp)(struct mg_connection *nc, union socket_address *sa)
void(* sock_set)(struct mg_connection *nc, sock_t sock)
int(* udp_recv)(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
int(* tcp_send)(struct mg_connection *nc, const void *buf, size_t len)
int(* tcp_recv)(struct mg_connection *nc, void *buf, size_t len)
const struct mg_iface_vtable * vtable
struct mg_connection * lc
union mg_lwip_conn_state::@24 pcb
struct mg_connection * nc
const union socket_address * sa
struct mg_connection * nc
struct mg_connection * nc
union socket_address * sa
struct mg_connection * nc
const struct mg_iface_vtable ** ifaces
const struct mg_iface_vtable * main_iface
struct mg_iface ** ifaces
uint16_t keep_alive_timer
struct mg_str will_message
struct mg_str protocol_name
void(* cb)(struct mg_mgr *mgr, void *arg)
mg_resolve_callback_t callback
bool rmdir(HNDLE hDB, HNDLE hROOT, const char *path)
static double comma(double a, double b)
static te_expr * base(state *s)
static te_expr * list(state *s)