ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

wss

2022-07-01 06:00:08  阅读:182  来源: 互联网

标签:break notice lws LWS wss lwsl mirror


最重要的是,windows的路径问题

 

/*
 * libwebsockets-test-client - libwebsockets test implementation
 *
 * Copyright (C) 2011-2017 Andy Green <andy@warmcat.com>
 *
 * This file is made available under the Creative Commons CC0 1.0
 * Universal Public Domain Dedication.
 *
 * The person who associated a work with this deed has dedicated
 * the work to the public domain by waiving all of his or her rights
 * to the work worldwide under copyright law, including all related
 * and neighboring rights, to the extent allowed by law. You can copy,
 * modify, distribute and perform the work, even for commercial purposes,
 * all without asking permission.
 *
 * The test apps are intended to be adapted for use in your code, which
 * may be proprietary.  So unlike the library itself, they are licensed
 * Public Domain.
 */

#include "lws_config.h"

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <signal.h>

#ifdef _WIN32
#define random rand
#include "gettimeofday.h"
#else
#include <syslog.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#include <libwebsockets.h>

struct lws_poly_gen {
    uint32_t cyc[2];
};

#define block_size (3 * 4096)

static int deny_deflate, longlived, mirror_lifetime, test_post, once;
static struct lws *wsi_dumb, *wsi_mirror;
static struct lws *wsi_multi[3];
static volatile int force_exit;
static unsigned int opts, rl_multi[3];
static int flag_no_mirror_traffic, justmirror, flag_echo;
static uint32_t count_blocks = 1024, txb, rxb, rx_count, errs;
static struct lws_poly_gen tx = { { 0xabcde, 0x23456789 } },
               rx = { { 0xabcde, 0x23456789 } }
;

#if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
char crl_path[1024] = "";
#endif

/*
 * This demo shows how to connect multiple websockets simultaneously to a
 * websocket server (there is no restriction on their having to be the same
 * server just it simplifies the demo).
 *
 *  dumb-increment-protocol:  we connect to the server and print the number
 *                we are given
 *
 *  lws-mirror-protocol: draws random circles, which are mirrored on to every
 *                client (see them being drawn in every browser
 *                session also using the test server)
 */

enum demo_protocols {

    PROTOCOL_DUMB_INCREMENT,
    PROTOCOL_LWS_MIRROR,

    /* always last */
    DEMO_PROTOCOL_COUNT
};

static uint8_t
lws_poly_rand(struct lws_poly_gen *p)
{
    p->cyc[0] = (p->cyc[0] & 1) ? (p->cyc[0] >> 1) ^ 0xb4bcd35c :
                      p->cyc[0] >> 1;
    p->cyc[0] = (p->cyc[0] & 1) ? (p->cyc[0] >> 1) ^ 0xb4bcd35c :
                      p->cyc[0] >> 1;
    p->cyc[1] = (p->cyc[1] & 1) ? (p->cyc[1] >> 1) ^ 0x7a5bc2e3 :
                      p->cyc[1] >> 1;

    return p->cyc[0] ^ p->cyc[1];
}

/*
static void show_http_content(const char *p, size_t l)
{
    if (lwsl_visible(LLL_INFO)) {
        while (l--)
            if (*p < 0x7f)
                putchar(*p++);
            else
                putchar('.');
    }
}
*/

/*
 * dumb_increment protocol
 *
 * since this also happens to be protocols[0], some callbacks that are not
 * bound to a specific protocol also turn up here.
 */



/* lws-mirror_protocol */

int gCount = 0;

static int
callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
            void *user, void *in, size_t len)
{
    unsigned char buf[LWS_PRE + block_size], *p;
    unsigned int rands[4];
    int l = 0;
    int n;

    switch (reason) {
    case LWS_CALLBACK_CLIENT_ESTABLISHED:

        lwsl_notice("mirror: LWS_CALLBACK_CLIENT_ESTABLISHED\n");

        if (flag_echo) {
            rxb = txb = 0;
            rx.cyc[0] = tx.cyc[0] = 0xabcde;
            rx.cyc[1] = tx.cyc[1] = 0x23456789;

            lws_callback_on_writable(wsi);

            break;
        }

        lws_get_random(lws_get_context(wsi), rands, sizeof(rands[0]));
        mirror_lifetime = 16384 + (rands[0] & 65535);
        /* useful to test single connection stability */
        if (longlived)
            mirror_lifetime += 500000;

        lwsl_notice("opened mirror connection with "
              "%d lifetime\n", mirror_lifetime);

        /*
         * mirror_lifetime is decremented each send, when it reaches
         * zero the connection is closed in the send callback.
         * When the close callback comes, wsi_mirror is set to NULL
         * so a new connection will be opened
         *
         * start the ball rolling,
         * LWS_CALLBACK_CLIENT_WRITEABLE will come next service
         */
        if (!flag_no_mirror_traffic)
            lws_callback_on_writable(wsi);
        break;

    case LWS_CALLBACK_CLIENT_CLOSED:
        lwsl_notice("mirror: LWS_CALLBACK_CLOSED mirror_lifetime=%d, "
                "rxb %d, rx_count %d\n", mirror_lifetime, rxb,
                rx_count);
        wsi_mirror = NULL;
        if (flag_echo || once)
            force_exit = 1;
        break;

    case LWS_CALLBACK_CLIENT_WRITEABLE:
        lwsl_user("LWS_CALLBACK_CLIENT_WRITEABLE\n");
        if (flag_no_mirror_traffic)
            return 0;
/*
        if (flag_echo) {
            for (n = 0; n < (int)block_size; n++)
                buf[LWS_PRE + n] = lws_poly_rand(&tx);

            n = lws_write(wsi, &buf[LWS_PRE], block_size,
                      opts | LWS_WRITE_TEXT);
            if (n < 0) {
                lwsl_err("Error sending\n");
                return -1;
            }

            txb++;
            if (txb != count_blocks)
                lws_callback_on_writable(wsi);
            else {
                lwsl_notice("send completed: %d x %d\n",
                        count_blocks, block_size);
            }
            break;
        }

        for (n = 0; n < 1; n++) {
            lws_get_random(lws_get_context(wsi), rands,
                       sizeof(rands));
            l += sprintf((char *)&buf[LWS_PRE + l],
                    "c #%06X %u %u %u;",
                    rands[0] & 0xffffff,    
                    rands[1] & 511,    
                    rands[2] & 255,        
                    (rands[3] & 31) + 1);    
        }
*/
        char str[1024] ={0};
        //strcpy(str,"{\"jsonrpc\" : \"2.0\",\"id\" : \"327\",\"method\" : \"Init\",\"params\" : {\"protocolVersion\" : \"1.0\",\"mac\" : \"8c:68:c8:d4:30:b8\",");
        //strcat(str,"\"version\" : \"V2.0.1T1\",\"boot\": \"V2.0.1T1\",\"configuration\": \"V2.0.1T1\",\"type\" : \"E8820V2-SHDX\",");
        //strcat(str,"\"serialNumber\" : \"HN51N6KHBA02378\",\"odm\":\"1\",\"areaCode\":\"\"}}");
        strcpy(str,"{\"params\": {\"configuration\": \"V1.0.0.0B5-0000\", \"type\": \"ZXHN E3630-0000\", \"version\": \"V1.0.0.2B4.0000_O\", \"protocolVersion\": \"1.0\", \"reversion\": \"V1.0.0.2B4.0000\", \"odm\": \"5\", \"mac\": \"e0:19:54:7f:ff:91\", \"serialNumber\": \"HN5EN84KAC00056\", \"areaCode\": \"\"}, \"jsonrpc\": \"2.0\", \"id\": \"2\", \"method\": \"Init\"}");
        //strcpy(str,"{\"params\": {\"configuration\": \"V1.0.0.0B5-0000\", \"type\": \"ZXHN E3630-0000\", \"version\": \"V1.0.0.2B4.0000_O\", \"protocolVersion\": \"1.0\", \"reversion\": \"V1.0.0.2B4.0000\", \"odm\": \"5\", \"mac\": \"e0:19:54:7f:ff:91\", \"serialNumber\": \"HN5EN84KAC00056\", \"areaCode\": \"\"}, \"jsonrpc\": \"2.0\", \"id\": \"2\", \"method\": \"SearchAll\"}");
        //strcpy(str,"{\"params\": {\"type\": \"ZXHN E3630-0000\",\"version\": \"V1.0.0.2B6.0000\",},\"jsonrpc\": \"2.0\",\"id\": \"2\",\"method\": \"PullUpgrade\"}");
        printf(" ---%s--- \n",str);

        if(gCount++ > 3){
            break;
        }

        strcpy((char*)&buf[LWS_PRE],str);

        n = lws_write(wsi, &buf[LWS_PRE], (unsigned int)strlen(str),
                  opts | LWS_WRITE_TEXT);
        if (n < 0)
            return -1;
        if (n < l) {
            lwsl_err("Partial write LWS_CALLBACK_CLIENT_WRITEABLE\n");
            return -1;
        }
        if (!justmirror)
            mirror_lifetime--;
        if (!mirror_lifetime) {
            lwsl_notice("closing mirror session\n");
            return -1;
        }
        /* get notified as soon as we can write again */
        lws_callback_on_writable(wsi);

#if !defined(_WIN32) && !defined(WIN32)
        usleep(50);
#endif
        break;

    case LWS_CALLBACK_CLIENT_RECEIVE:
        printf("---LWS_CALLBACK_CLIENT_RECEIVE----%s---%ld-->\n",(char*)in,len);
        if (flag_echo) {
            p = (unsigned char *)in;
            for (n = 0; n < (int)len; n++)
                if (*p++ != lws_poly_rand(&rx)) {
                    lwsl_err("mismatch at rxb %d offset %d\n", rxb + (n / block_size), n % block_size);
                    errs++;
                    force_exit = 1;
                    return -1;
                }
            rx_count += (unsigned int)(unsigned long long)len;
            while (rx_count >= block_size) {
                rx_count -= block_size;
                rxb++;
            }
            if (rx_count == 0 && rxb == count_blocks) {
                lwsl_notice("Everything received: errs %d\n",
                        errs);
                force_exit = 1;
                return -1;
            }
        }
        break;
    default:
        break;
    }

    return 0;
}
//wss://appstore-gw.ztehome.com.cn:443/tunnel?mac=a8:74:84:e8:3b:94&sn=HN5YN81M7616415&type=ZXHN%20E1600-1000A&version=V1.0.0.2B1.1000&reversion=V1.1.0.5B4.1000

/*
static int
callback_test_raw_client(struct lws *wsi, enum lws_callback_reasons reason,
             void *user, void *in, size_t len)
{
    switch (reason) {
    case LWS_CALLBACK_RAW_ADOPT:
        lwsl_notice("LWS_CALLBACK_RAW_ADOPT\n");
        break;

    case LWS_CALLBACK_RAW_RX:
        lwsl_notice("LWS_CALLBACK_RAW_RX %ld\n", (long)len);
        puts(in);
        break;

    case LWS_CALLBACK_RAW_CLOSE:
        lwsl_notice("LWS_CALLBACK_RAW_CLOSE\n");
        break;

    case LWS_CALLBACK_RAW_WRITEABLE:
        lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE\n");
        break;

    default:
        break;
    }

    return 0;
}
*/
/* list of supported protocols and callbacks */

static const struct lws_protocols protocols[] = {
    /*
    {
        "dumb-increment-protocol",
        callback_dumb_increment,
        0,
        20,
    },*/
    {
        "lws-mirror-protocol",
        callback_lws_mirror,
        0,
        4096,
    }, 
    /*
    {
        "lws-test-raw-client",
        callback_test_raw_client,
        0,
        128
    },*/
    { NULL, NULL, 0, 0 } /* end */
};

static const struct lws_extension exts[] = {
    {
        "permessage-deflate",
        lws_extension_callback_pm_deflate,
        "permessage-deflate; client_no_context_takeover"
    },
    {
        "deflate-frame",
        lws_extension_callback_pm_deflate,
        "deflate_frame"
    },
    { NULL, NULL, NULL /* terminator */ }
};



void sighandler(int sig)
{
    force_exit = 1;
}

static struct option options[] = {
    { "help",    no_argument,        NULL, 'h' },
    { "debug",      required_argument,      NULL, 'd' },
    { "port",    required_argument,    NULL, 'p' },
    { "ssl",    no_argument,        NULL, 's' },
    { "strict-ssl",    no_argument,        NULL, 'S' },
    { "version",    required_argument,    NULL, 'v' },
    { "undeflated",    no_argument,        NULL, 'u' },
    { "echo",    no_argument,        NULL, 'e' },
    { "multi-test",    no_argument,        NULL, 'm' },
    { "nomirror",    no_argument,        NULL, 'n' },
    { "justmirror",    no_argument,        NULL, 'j' },
    { "longlived",    no_argument,        NULL, 'l' },
    { "post",    no_argument,        NULL, 'o' },
    { "once",    no_argument,        NULL, 'O' },
    { "pingpong-secs", required_argument,    NULL, 'P' },
    { "ssl-cert",  required_argument,    NULL, 'C' },
    { "ssl-key",  required_argument,    NULL, 'K' },
    { "ssl-ca",  required_argument,        NULL, 'A' },
#if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
    { "ssl-crl",  required_argument,        NULL, 'R' },
#endif
    { NULL, 0, 0, 0 }
};

static int ratelimit_connects(unsigned int *last, unsigned int secs)
{
    struct timeval tv;

    gettimeofday(&tv, NULL);

    if (tv.tv_sec - (*last) < secs)
        return 0;

    *last = tv.tv_sec;

    return 1;
}

int main(int argc, char **argv)
{
    int n = 0, m, ret = 0, port = 7681, use_ssl = 0, ietf_version = -1;
    unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, pp_secs = 0,
             do_multi = 0;
    struct lws_context_creation_info info;
    struct lws_client_connect_info i;
    struct lws_context *context;
    const char *prot, *p;
    char path[300];
    char cert_path[1024] = "";
    char key_path[1024] = "";
    char ca_path[1024] = "";
    unsigned long last = lws_now_secs();

    

    memset(&info, 0, sizeof info);

    lwsl_notice("libwebsockets test client - license LGPL2.1+SLE\n");
    lwsl_notice("(C) Copyright 2010-2018 Andy Green <andy@warmcat.com>\n");

    if (argc < 2)
        goto usage;

    while (n >= 0) {
        n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moeO", options,
                NULL);
        if (n < 0)
            continue;
        switch (n) {
        case 'd':
            lws_set_log_level(atoi(optarg), NULL);
            break;
        case 's': /* lax SSL, allow selfsigned, skip checking hostname */
            use_ssl = LCCSCF_USE_SSL |
                  LCCSCF_ALLOW_SELFSIGNED |
                  LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
            break;
        case 'S': /* Strict SSL, no selfsigned, check server hostname */
            use_ssl = LCCSCF_USE_SSL;
            break;
        case 'p':
            port = atoi(optarg);
            break;
        case 'e':
            flag_echo = 1;
            break;
        case 'P':
            pp_secs = atoi(optarg);
            lwsl_notice("Setting pingpong interval to %d\n", pp_secs);
            break;
        case 'j':
            justmirror = 1;
            break;
        case 'l':
            longlived = 1;
            break;
        case 'v':
            ietf_version = atoi(optarg);
            break;
        case 'u':
            deny_deflate = 1;
            break;
        case 'm':
            do_multi = 1;
            break;
        case 'o':
            test_post = 1;
            break;
        case 'O':
            once = 1;
            break;
        case 'n':
            flag_no_mirror_traffic = 1;
            lwsl_notice("Disabled sending mirror data (for pingpong testing)\n");
            break;
        case 'C':
            lws_strncpy(cert_path, optarg, sizeof(cert_path));
            break;
        case 'K':
            lws_strncpy(key_path, optarg, sizeof(key_path));
            break;
        case 'A':
            lws_strncpy(ca_path, optarg, sizeof(ca_path));
            break;

#if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
        case 'R':
            lws_strncpy(crl_path, optarg, sizeof(crl_path));
            break;
#endif
        case 'h':
            goto usage;
        }
    }

    if (optind >= argc)
        goto usage;

    signal(SIGINT, sighandler);

    memset(&i, 0, sizeof(i));

    i.port = port;
    if (lws_parse_uri(argv[optind], &prot, &i.address, &i.port, &p))
        goto usage;

    /* add back the leading / on path */
    if (p[0] != '/') {
        path[0] = '/';
        lws_strncpy(path + 1, p, sizeof(path) - 1);
        i.path = path;
    } else
        i.path = p;

    if (!strcmp(prot, "http") || !strcmp(prot, "ws"))
        use_ssl = 0;
    if (!strcmp(prot, "https") || !strcmp(prot, "wss"))
        if (!use_ssl)
            use_ssl = LCCSCF_USE_SSL;

    lwsl_debug("'%s' %p '%s' %p\n", i.address, i.address, i.path, i.path);

    /*
     * create the websockets context.  This tracks open connections and
     * knows how to route any traffic and which protocol version to use,
     * and if each connection is client or server side.
     *
     * For this client-only demo, we tell it to not listen on any port.
     */
    info.http_proxy_address = "proxy.XXX.com.cn";
    info.http_proxy_port = 80;
    info.port = CONTEXT_PORT_NO_LISTEN;
    info.protocols = protocols;
    info.gid = -1;
    info.uid = -1;
    info.ws_ping_pong_interval = pp_secs;
    info.extensions = exts;

#if defined(LWS_WITH_TLS)
    info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
#endif

    //wth0630
    use_ssl = LCCSCF_USE_SSL | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_EXPIRED| LCCSCF_ALLOW_SELFSIGNED;
    //

    if (use_ssl) {
        /*
         * If the server wants us to present a valid SSL client certificate
         * then we can set it up here.
         */

        if (cert_path[0])
            info.client_ssl_cert_filepath = cert_path;
        if (key_path[0])
            info.client_ssl_private_key_filepath = key_path;

        /*
         * A CA cert and CRL can be used to validate the cert send by the server
         */
        if (ca_path[0])
            info.client_ssl_ca_filepath = ca_path;

        printf("client_ssl_ca_filepath =%s \n",info.client_ssl_ca_filepath);
        
        info.client_ssl_cert_filepath =  "cloud.crt";
        info.client_ssl_private_key_filepath = "cloud.key.unsecure";
        info.client_ssl_ca_filepath ="ca.crt";


#if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param)
        else if (crl_path[0])
            lwsl_notice("WARNING, providing a CRL requires a CA cert!\n");
#endif
    }

    if (use_ssl & LCCSCF_USE_SSL) {
        lwsl_notice(" Using SSL\n");
#if defined(LWS_WITH_MBEDTLS)
        lwsl_notice("   (NOTE: mbedtls needs to be given the remote\n");
        lwsl_notice("    CA cert to trust (with -A) to validate it)\n");
#endif
    }
    else
        lwsl_notice(" SSL disabled\n");
    if (use_ssl & LCCSCF_ALLOW_SELFSIGNED)
        lwsl_notice(" Selfsigned certs allowed\n");
    else
        lwsl_notice(" Cert must validate correctly (use -s to allow selfsigned)\n");
    if (use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)
        lwsl_notice(" Skipping peer cert hostname check\n");
    else
        lwsl_notice(" Requiring peer cert hostname matches\n");

    context = lws_create_context(&info);
    if (context == NULL) {
        fprintf(stderr, "Creating libwebsocket context failed\n");
        return 1;
    }

    i.context = context;
    i.ssl_connection = use_ssl;
    i.host = i.address;
    i.origin = i.address;
    i.ietf_version_or_minus_one = ietf_version;

    if (!strcmp(prot, "http") || !strcmp(prot, "https")) {
        lwsl_notice("using %s mode (non-ws)\n", prot);
        if (test_post) {
            i.method = "POST";
            lwsl_notice("POST mode\n");
        }
        else
            i.method = "GET";
        do_ws = 0;
    } else
        if (!strcmp(prot, "raw")) {
            i.method = "RAW";
            i.protocol = "lws-test-raw-client";
            lwsl_notice("using RAW mode connection\n");
            do_ws = 0;
        } else
            lwsl_notice("using %s mode (ws)\n", prot);

    /*
     * sit there servicing the websocket context to handle incoming
     * packets, and drawing random circles on the mirror protocol websocket
     *
     * nothing happens until the client websocket connection is
     * asynchronously established... calling lws_client_connect() only
     * instantiates the connection logically, lws_service() progresses it
     * asynchronously.
     */

    m = 0;
    while (!force_exit) {

        if (do_multi) {
            for (n = 0; n < (int)LWS_ARRAY_SIZE(wsi_multi); n++) {
                if (!wsi_multi[n] && ratelimit_connects(&rl_multi[n], 2u)) {
                    lwsl_notice("dumb %d: connecting\n", n);
                    i.protocol = protocols[PROTOCOL_DUMB_INCREMENT].name;
                    i.pwsi = &wsi_multi[n];
                    lws_client_connect_via_info(&i);
                }
            }
        } else {

            if (do_ws) {
                if (!flag_echo && !justmirror && !wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) {
                    lwsl_notice("dumb: connecting\n");
                    i.protocol = protocols[PROTOCOL_DUMB_INCREMENT].name;
                    i.pwsi = &wsi_dumb;
                    lws_client_connect_via_info(&i);
                }

                if (!wsi_mirror && ratelimit_connects(&rl_mirror, 2u)) {
                    lwsl_notice("mirror: connecting\n");
                    i.protocol = protocols[PROTOCOL_LWS_MIRROR].name;
                    i.pwsi = &wsi_mirror;
                    wsi_mirror = lws_client_connect_via_info(&i);
                }
            } else
                if (!wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) {
                    lwsl_notice("http: connecting\n");
                    i.pwsi = &wsi_dumb;
                    lws_client_connect_via_info(&i);
                }
        }

        lws_service(context, 500);

        if (do_multi) {
            m++;
            if (m == 10) {
                m = 0;
                lwsl_notice("doing lws_callback_on_writable_all_protocol\n");
                lws_callback_on_writable_all_protocol(context,
                       &protocols[PROTOCOL_DUMB_INCREMENT]);
            }
        }

        if (flag_echo && lws_now_secs() != last) {
            lwsl_notice("rxb %d, rx_count %d\n", rxb, rx_count);
            last = lws_now_secs();
        }
    }

    lwsl_err("Exiting\n");
    lws_context_destroy(context);

    return ret;

usage:
    fprintf(stderr, "Usage: libwebsockets-test-client "
                "<server address> [--port=<p>] "
                "[--ssl] [-k] [-v <ver>] "
                "[-d <log bitfield>] [-l]\n");
    return 1;
}

 

标签:break,notice,lws,LWS,wss,lwsl,mirror
来源: https://www.cnblogs.com/cnchengv/p/16433245.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有