Save
Saving
  • G
    guluting

    其实当初想设计转发模块的时候是计划在框架内部实现负载均衡的功能的,但是经过测试发现效率并没有提升,我做了很多测试也尝试将代码在协程与多线程之间就行调优,但是速度始终不理想,最终还是使用Nginx去实现Tornado的多进程转发模式了。多进程配合Tornado的协程速度还是不错的。

    socket转发

    from tornado.tcpserver import TCPServer
    from tornado.ioloop  import IOLoop
    import tornado
    import socket
    import threading
    import logging
    from concurrent.futures import ThreadPoolExecutor
    import random
    
    from gevent import monkey
    monkey.patch_all()
    
    class Connection():
        def __init__(self,proxy, stream, address):
            print threading.current_thread()
            self._proxy = proxy
            self._proxy.clients.add(self)
            logging.debug("[connect] clients count:"+str(len(self._proxy.clients)))
            self._stream = stream
            self._address = address
            self._stream.set_close_callback(self.on_close)
            self.http_content = ""
            self.read_data()
    
        def read_data(self):
            self._stream.read_until("\r\n\r\n",self.analysis_head)
    
        def analysis_head(self, head):
            self.http_content = head
            fields = head.split("\r\n")
            field_map = {}
            for field in fields:
                kv = field.split(":")
                if len(kv) == 2:
                    field_map[kv[0].lower()] = kv[1]
            if field_map.has_key("content-length"):
                self._stream.read_bytes(int(field_map["content-length"]),self.proxy_data)
    
        def write_finish(self):
            if self._stream.closed():
                return
            self._stream.close()
    
        def recvall(self, sock):
            BUFF_SIZE = 1024
            data = b''
            while True:
                part = sock.recv(BUFF_SIZE)
                data += part
                if len(part) < BUFF_SIZE:
                    break
            return data
    
        def proxy_data(self, data):
            self.http_content += data
            logging.debug("http content:"+self.http_content)
            cur_server = ()
            if self._proxy.mode == 0:
                self._proxy.mutex.acquire()
                cur_server = self._proxy.server_list[self._proxy.cur_server]
                self._proxy.cur_server += 1
                if self._proxy.cur_server == self._proxy.server_count:
                    self._proxy.cur_server = 0
                self._proxy.mutex.release()
            if self._proxy.mode == 1:
                self._proxy.cur_server = random.randint(0,self._proxy.server_count-1)
                cur_server = self._proxy.server_list[self._proxy.cur_server]
    
            logging.debug("proxy -> "+cur_server[0]+":"+str(cur_server[1]))
    
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(cur_server)
            s.send(self.http_content)
            ret_data = self.recvall(s)
            if not self._stream.closed():
                self._stream.write(ret_data,self.write_finish)
            s.close()
    
        def on_close(self):
            self._proxy.clients.remove(self)
            logging.debug("[close] clients count:"+str(len(self._proxy.clients)))
    
    
    class Proxy(TCPServer):
        def __init__(self, port, server_list, mode):
            super(Proxy,self).__init__()
            self.clients = set()
            self.port = port
            self.server_list = server_list
            self.mode = mode
            self.cur_server = 0
            self.server_count = len(server_list)
            self.mutex = threading.Lock()
            self.executor = ThreadPoolExecutor()
    
        def worker(self, stream, address):
            Connection(self,stream, address)
    
        def handle_stream(self, stream, address):
            # self.executor.submit(self.worker, stream, address)
            Connection(self,stream, address)
    
        def start(self):
            self.listen(self.port)
            IOLoop.instance().start()
    

    tornado.httpclient.AsyncHTTPClient()转发

    import tornado.ioloop
    import tornado.web
    import tornado.httpclient
    import tornado.gen
    import logging
    import threading
    
    from gevent import monkey
    monkey.patch_all()
    
    
    class MainHandler(tornado.web.RequestHandler):
    
        def get(self, *args, **kwargs):
            try:
                logging.debug(str(self.request.remote_ip)+"\n"+"-"*80+"\n"+str(self.request.body)+"\n"+"-"*80)
                self.application.analysis.decrypt_http(self.request.body,self)
            except Exception as e: logging.error(str(e))
    
        def handle_request(self, response):
            if not response.error:
                self.write(response.body)
            self.finish()
    
        @tornado.web.asynchronous
        def post(self, *args, **kwargs):
            try:
                logging.debug(str(self.request.remote_ip)+"\n"+"-"*80+"\n"+str(self.request.body)+"\n"+"-"*80)
                if self.application.mode == 0:
                    self.application.mutex.acquire()
                    cur_server = self.application.servers[self.application.cur_server]
                    self.application.cur_server += 1
                    if self.application.cur_server == self.application.server_count:
                        self.application.cur_server = 0
                    self.application.mutex.release()
                    logging.debug("proxy -> "+cur_server)
                    headers = self.request.headers
                    body = self.request.body
                    request = tornado.httpclient.HTTPRequest(cur_server,
                                                     method="POST", headers=headers, body=body, validate_cert=False)
                    tornado.httpclient.AsyncHTTPClient().fetch(request,self.handle_request)
            except Exception as e: logging.error(str(e))
    
    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])
    
    class Proxy():
        def __init__(self, port, servers, mode):
            self._port = port
            self._servers = servers
            self._mode = mode
    
        def start(self):
            app = make_app()
            app.listen(self._port)
            app.mode = self._mode
            app.servers = self._servers
            app.cur_server = 0
            app.server_count = len(self._servers)
            app.mutex = threading.Lock()
            tornado.ioloop.IOLoop.current().start()
    

    posted in GuaiK实验室 read more
  • G
    guluting

    @pipi vscode还是比较好用的,我现在都很少用IDE了,除了开发Qt程序会用QtCreator😐

    posted in GuaiK重灾区 read more
  • G
    guluting

    哈哈,其实我没看懂😀 可以介绍下作品吗

    posted in GuaiK工厂 read more
  • G
    guluting

    重点讲解:
    装饰器(@)是Python中非常重要的『东西』,你在微博中艾特谁,她还是她,你改变不了她。但是在python中你艾特了某个函数,你将对它拥有控制权,哪怕把它改的面目全非也是可以的。
    装饰器是什么意思呢?
    装饰器就是一个接受函数对象的函数,好吧,有点绕口,请看代码:

    class Girl():
        def __init__(self):
            self.msg = "Girl:I dislike you!"
        def output(self):
            return self.msg
    
    def Change(obj):
        # 洗脑模式
        obj.msg = "Girl:I like you!"
        return obj
    
    print Change(Girl()).output()
    # 输出结果:Girl:I like you!
    

    那么显然写成Change(Girl()).output()不是很直观,我们来换一种更Pythoner的:
    直接通过装饰器去改写输出函数output,在函数输出前修改msg数据

    def ChangeOutput(msg):
        def change_output(func):
            def new_output(s):
                s.msg = "Girl:I like you!"
                return func(s)
            return new_output
        return change_output
    
    class Girl():
        instance = None
        def __init__(self):
            self.msg = "Girl:I dislike you!"
    
        @ChangeOutput("Girl:I link you!")
        def output(self):
            return self.msg
    
    print Girl().output()
    

    下面就是用装饰器来模拟Flask的原理了。

    # -*- coding: utf-8 -*-
    class GuaikNet():
        def __init__(self):
            # URI与处理函数的映射
            self._func_map = {}
    
        def route(self, uri):       # 装饰器,用来接受参数
            def _new_func(func):    # 新的函数对象,用来替代被装饰的函数,参数为被装饰的函数对象
                self._func_map[uri] = func
                return func
            return _new_func
    
        def server(self, uri):
            func = self._func_map[uri]
            if func:
                return func()
            else:
                raise ValueError('Route "{}" has not been registered'.format(uri))
    
    app = GuaikNet()
    @app.route("/")
    def hello():
        return "Hello GuaikNet"
    
    print app.server("/")
    

    posted in GuaiK实验室 read more
  • G
    guluting

    VSCode是微软出品的一款比较轻量的文本编辑工具,和Github出品的Atom类似,而且都提供了很强大的插件功能。
    CMake是一款跨平台的编译工具,它能够生成各种项目文件或makefile文件。
    决定使用VSCode+CMake编译驱动的主要原因是感觉Visual Studio太过于臃肿了吧,自从写驱动程序以来都经历过了使用文本编辑器或者VC++6.0开发,微软的产品功能越来越全面的同时也会让产品变得太臃肿了。开发驱动程序脚本编辑器足矣。


    下面需要准备的工具(自行安装):

    下载WDK

    https://docs.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk

    下载VSCode

    https://code.visualstudio.com/

    下载CMake

    https://cmake.org/download/

    下载FindWDK项目(用来搜索WDK相关路径)

    https://github.com/SergiusTheBest/FindWDK.git


    建立工程目录:

    NetFilter(主目录)
    |--cmake
        |--FindWdk.cmake     # 在FindWDK中复制过来
    |--network               # FWPM网络过滤模块
        |--main.c
        |--CMakeLists.txt
    |--CMakeLists.txt        # CMake配置文件
    |--build.bat             # 自动编译脚本
    

    相关代码

    network->main.c

    #pragma once
    #pragma warning(push)
    #pragma warning(disable : 4201)
    #pragma warning(disable : 4324)
    #define NDIS_SUPPORT_NDIS6 1
    #include <ntifs.h>
    #include <ntddk.h>
    #include <ndis.h>
    #include <fwpsk.h>
    #include <fwpmk.h>
    #include <wdm.h>
    #pragma warning(pop)
    #define INITGUID
    #include <guiddef.h>
    
    #define DEVICE_NAME L"\\Device\\GhostNet"
    #define DEVICE_DOSNAME L"\\DosDevices\\GhostNet"
    #define kmalloc(_s) ExAllocatePoolWithTag(NonPagedPool, _s, 'GSYS')
    #define kfree(_p) ExFreePool(_p)
    
    DEFINE_GUID
        (
            GUID_ALE_AUTH_CONNECT_CALLOUT_V4,
            0x6812fc83,
            0x7d3e,
            0x499a,
            0xb8, 0x59,
            0x55, 0xe0, 0xd8, 0x5f, 0x34, 0x8b);
    
    
    
    PDEVICE_OBJECT gDevObj;
    HANDLE gEngineHandle = 0;
    HANDLE gInjectHandle = 0;
    
    UINT32 gAleConnectCalloutId = 0;
    UINT64 gAleConnectFilterId = 0;
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING regPath);
    VOID DriverUnload(PDRIVER_OBJECT driver);
    
    //协议代码转为名称
    char *ProtocolIdToName(UINT16 id)
    {
        char *ProtocolName = (char *)kmalloc(16);
        switch (id)
        {
        case 1:
            strcpy_s(ProtocolName, 4 + 1, "ICMP");
            break;
        case 2:
            strcpy_s(ProtocolName, 4 + 1, "IGMP");
            break;
        case 6:
            strcpy_s(ProtocolName, 3 + 1, "TCP");
            break;
        case 17:
            strcpy_s(ProtocolName, 3 + 1, "UDP");
            break;
        case 27:
            strcpy_s(ProtocolName, 3 + 1, "RDP");
            break;
        default:
            strcpy_s(ProtocolName, 7 + 1, "UNKNOWN");
            break;
        }
        return ProtocolName;
    }
    
    NTSTATUS NTAPI WallNotifyFn(
        IN FWPS_CALLOUT_NOTIFY_TYPE notifyType,
        IN const GUID *filterKey,
        IN const FWPS_FILTER *filter)
    {
        return STATUS_SUCCESS;
    }
    
    VOID NTAPI WallFlowDeleteFn(
        IN UINT16 layerId,
        IN UINT32 calloutId,
        IN UINT64 flowContext)
    {
        return;
    }
    
    
    
    // 连接过滤
    void NTAPI ALEConnectClassify(
        IN const FWPS_INCOMING_VALUES0 *inFixedValues,
        IN const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
        IN OUT void *layerData,
        IN const void *classifyContext,
        IN const FWPS_FILTER *filter,
        IN UINT64 flowContext,
        OUT FWPS_CLASSIFY_OUT *classifyOut)
    {
        char *ProtocolName = NULL;
        DWORD LocalIp, RemoteIP;
        LocalIp = inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
        RemoteIP = inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
        ProtocolName = ProtocolIdToName(inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint16);
        DbgPrint("[WFP]IRQL=%d;PID=%ld;Path=%S;Local=%u.%u.%u.%u:%d;Remote=%u.%u.%u.%u:%d;Protocol=%s\n",
                 (USHORT)KeGetCurrentIrql(),
                 (DWORD)(inMetaValues->processId),
                 (PWCHAR)inMetaValues->processPath->data, //NULL,//
                 (LocalIp >> 24) & 0xFF, (LocalIp >> 16) & 0xFF, (LocalIp >> 8) & 0xFF, LocalIp & 0xFF,
                 inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT].value.uint16,
                 (RemoteIP >> 24) & 0xFF, (RemoteIP >> 16) & 0xFF, (RemoteIP >> 8) & 0xFF, RemoteIP & 0xFF,
                 inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT].value.uint16,
                 ProtocolName);
        
        kfree(ProtocolName);
        classifyOut->actionType = FWP_ACTION_PERMIT; //允许连接
    
        //禁止IE联网(设置“行动类型”为FWP_ACTION_BLOCK)
        // if(wcsstr((PWCHAR)inMetaValues->processPath->data,L"iexplore.exe"))
        // {
        // classifyOut->actionType = FWP_ACTION_BLOCK;
        // classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
        // classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
        // }
        return;
    }
    
    
    /*
    * 注册过滤层回调函数
    */
    NTSTATUS RegisterCalloutForLayer(
        IN const GUID *layerKey,
        IN const GUID *calloutKey,
        IN FWPS_CALLOUT_CLASSIFY_FN classifyFn,
        IN FWPS_CALLOUT_NOTIFY_FN notifyFn,
        IN FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN flowDeleteNotifyFn,
        OUT UINT32 *calloutId,
        OUT UINT64 *filterId)
    {
        NTSTATUS status = STATUS_SUCCESS;
        FWPS_CALLOUT sCallout = {0};
        FWPM_FILTER mFilter = {0};
        FWPM_FILTER_CONDITION mFilter_condition[1] = {0};
        FWPM_CALLOUT mCallout = {0};
        FWPM_DISPLAY_DATA mDispData = {0};
        BOOLEAN bCalloutRegistered = FALSE;
        sCallout.calloutKey = *calloutKey;
        sCallout.classifyFn = classifyFn;
        sCallout.flowDeleteFn = flowDeleteNotifyFn;
        sCallout.notifyFn = notifyFn;
        status = FwpsCalloutRegister(gDevObj, &sCallout, calloutId);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("FwpsCalloutRegister failed.");
            goto exit;
        }
        bCalloutRegistered = TRUE;
        mDispData.name = L"WFP TEST";
        mDispData.description = L"TESLA.ANGELA's WFP TEST";
        mCallout.applicableLayer = *layerKey;
        mCallout.calloutKey = *calloutKey;
        mCallout.displayData = mDispData;
        status = FwpmCalloutAdd(gEngineHandle, &mCallout, NULL, NULL);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("FwpmCalloutAdd falied");
            goto exit;
        }
        mFilter.action.calloutKey = *calloutKey;
        mFilter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
        mFilter.displayData.name = L"WFP TEST";
        mFilter.displayData.description = L"TESLA.ANGELA's WFP TEST";
        mFilter.layerKey = *layerKey;
        mFilter.numFilterConditions = 0;
        mFilter.filterCondition = mFilter_condition;
        mFilter.subLayerKey = FWPM_SUBLAYER_UNIVERSAL;
        mFilter.weight.type = FWP_EMPTY;
        status = FwpmFilterAdd(gEngineHandle, &mFilter, NULL, filterId);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("FwpmFilterAdd failed");
            goto exit;
        }
    exit:
        if (!NT_SUCCESS(status))
        {
            if (bCalloutRegistered)
            {
                FwpsCalloutUnregisterById(*calloutId);
            }
        }
        return status;
    }
    
    NTSTATUS WallRegisterCallouts()
    {
        NTSTATUS status = STATUS_SUCCESS;
        BOOLEAN bInTransaction = FALSE;
        BOOLEAN bEngineOpened = FALSE;
        FWPM_SESSION session = {0};
        session.flags = FWPM_SESSION_FLAG_DYNAMIC;
        status = FwpmEngineOpen(NULL,
                                RPC_C_AUTHN_WINNT,
                                NULL,
                                &session,
                                &gEngineHandle);
        if (!NT_SUCCESS(status))
            goto exit;
        bEngineOpened = TRUE;
        status = FwpmTransactionBegin(gEngineHandle, 0);
        if (!NT_SUCCESS(status))
            goto exit;
        bInTransaction = TRUE;
        // 注册Connect
        status = RegisterCalloutForLayer(
            &FWPM_LAYER_ALE_AUTH_CONNECT_V4,
            &GUID_ALE_AUTH_CONNECT_CALLOUT_V4,
            ALEConnectClassify,
            WallNotifyFn,
            WallFlowDeleteFn,
            &gAleConnectCalloutId,
            &gAleConnectFilterId);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("RegisterCalloutForLayer-FWPM_LAYER_ALE_AUTH_CONNECT_V4 failed!\n");
            goto exit;
        }
    
        status = FwpmTransactionCommit(gEngineHandle);
        if (!NT_SUCCESS(status))
            goto exit;
        bInTransaction = FALSE;
    exit:
        if (!NT_SUCCESS(status))
        {
            if (bInTransaction)
            {
                FwpmTransactionAbort(gEngineHandle);
            }
            if (bEngineOpened)
            {
                FwpmEngineClose(gEngineHandle);
                gEngineHandle = 0;
            }
        }
        return status;
    }
    
    NTSTATUS WallUnRegisterCallouts()
    {
        if (gEngineHandle != 0)
        {
            // 删除FilterId
            FwpmFilterDeleteById(gEngineHandle, gAleConnectFilterId);
            // 删除CalloutId
            FwpmCalloutDeleteById(gEngineHandle, gAleConnectCalloutId);
            // 清空FilterId
            gAleConnectFilterId = 0;
            // 反注册CalloutId
            FwpsCalloutUnregisterById(gAleConnectCalloutId);
            // 清空CalloutId
            gAleConnectCalloutId = 0;
            // 关闭引擎
            FwpmEngineClose(gEngineHandle);
            gEngineHandle = 0;
        }
        return STATUS_SUCCESS;
    }
    
    // #pragma alloc_text(PAGE, DriverUnload)
    VOID DriverUnload(PDRIVER_OBJECT driver)
    {
        UNICODE_STRING DeviceDosName;
        WallUnRegisterCallouts();
        RtlInitUnicodeString(&DeviceDosName,DEVICE_DOSNAME);
        IoDeleteSymbolicLink(&DeviceDosName);
        IoDeleteDevice(driver->DeviceObject);
    }
    
    NTSTATUS DefIRPHandler(IN PDEVICE_OBJECT devobj, IN PIRP Irp){
        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }
    
    NTSTATUS CreateIRPHandler(IN PDEVICE_OBJECT devobj, IN PIRP Irp){
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }
    
    NTSTATUS CloseIRPHandler(IN PDEVICE_OBJECT devobj, IN PIRP Irp){
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }
    
    // #pragma alloc_text(INIT, DriverEntry)
    NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING regPath)
    {
        // PAGED_CODE();
        NTSTATUS status;
        UNICODE_STRING DeviceName,DeviceDosName;
        RtlInitUnicodeString(&DeviceName,DEVICE_NAME);
        RtlInitUnicodeString(&DeviceDosName,DEVICE_DOSNAME);
        // 设置默认IRP派遣处理函数
        for(UINT i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++){
            driver->MajorFunction[i] = DefIRPHandler;
        }
        //  IRP 打开关闭处理函数
        driver->MajorFunction[IRP_MJ_CREATE] = CreateIRPHandler;
        driver->MajorFunction[IRP_MJ_CLOSE] = CloseIRPHandler;
        driver->DriverUnload = DriverUnload;
        status = IoCreateDevice(driver,
                                0,
                                NULL,
                                FILE_DEVICE_UNKNOWN,
                                0, TRUE,
                                &gDevObj);
        if (!NT_SUCCESS(status))
            return status;
        if (!gDevObj)
            return STATUS_UNEXPECTED_IO_ERROR;
        status = WallRegisterCallouts();
        if (!NT_SUCCESS(status))
            return status;
        
    
        // 设置设备读写方式
        gDevObj->Flags |= DO_DIRECT_IO;
        // 创建符号链接
        status = IoCreateSymbolicLink(&DeviceDosName, &DeviceName);
        gDevObj->Flags &= ~ DO_DEVICE_INITIALIZING;
        return STATUS_SUCCESS;
    }
    

    network->CMakeLists.txt

    SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/./build)
    wdk_add_driver(network main.c)
    target_link_libraries(network ntoskrnl ndis fwpkclnt uuid)
    

    NetFilter->CMakeLists.txt
    其中需要自己设置一下WDK Library链接的路径

    cmake_minimum_required(VERSION 3.0)
    
    project(NetFilter)
    
    set_property(GLOBAL PROPERTY USE_FOLDERS ON)
    
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W0 /WX")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W0 /WX")
    
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/./cmake")
    find_package(WDK REQUIRED)
    
    # 设置WDK Library路径
    link_directories("C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.17134.0\\km\\x86")
    add_subdirectory(comport)
    add_subdirectory(network)
    

    NetFilter->build.bat
    如果需要编译Release版本的请替换脚本中的Debug字符串

    cmake .
    devenv ./NetFilter.sln /Build "Debug"
    

    祝你成功编译出sys文件 😈
    0_1540261742778_WX20181023-102839@2x.png

    posted in GuaiK重灾区 read more
  • G
    guluting

    收费的,不过价格不贵。短信验证的签名不需要审核,你在brand中填什么它就给你显示什么,及时性还不错。

    posted in GuaiK实验室 read more
  • G
    guluting

    NEXMO官网

    https://www.nexmo.com/

    短信验证码发送与验证实例


    api_key和api_secret替换成你自己的。


    import logging
    import requests
    
    api_key = "your_api_key"
    api_secret = "your_api_secret"
    brand = "Guaik"
    
    def sendVerifyCode(self,number):
        # param  : number 接收验证码的手机号
        # retval : 返回请求id,在验证的时候会用到
        request_id = None
        try:
            data = {"api_key":api_key,"api_secret":api_secret,"number":number,"brand":brand}
            headers = {'Content-Type': 'application/json'}
            r = requests.post("https://api.nexmo.com/verify/json",headers = headers, data = json.dumps(data))
            data = json.loads(r.text)
            if data["status"] == "0":
                request_id = data["request_id"]
        except Exception as e: logging.error(e)
        return request_id
    
    
    def checkCode(self,request_id,code):
        # param request_id : 请求id,在发送验证码成功时返回
        # param code       : 手机接收到的验证码
        # retval           : 验证成功返回True
        result = False
        try:
            data = {"api_key":api_key,"api_secret":api_secret,"request_id":request_id,"code":code}
            headers = {'Content-Type': 'application/json'}
            r = requests.post("https://api.nexmo.com/verify/check/json",headers = headers, data = json.dumps(data))
            data = json.loads(r.text)
            if data["status"] == "0":
                result = True
        except Exception as e: logging.error(e)
        return result
    
    

    posted in GuaiK实验室 read more
  • G
    guluting

    0_1540200643035_Anonymous.jpg

    《GuaiK实验室》为何成立:

    很多人都希望有一个能够展现自己技能的舞台,当厌倦了重复性的设计工作,我们更喜欢通过自己的技术去创造出与众不同的产品。当大家都以盈利为最终目的的同时,我们确始于设计出一款能够让大家觉得新鲜,好玩,有趣的产品。我们不盲从不跟随,希望我们的产品能够让大家觉得实用,能够给人们的生活带来便捷和有趣。当有更多的人接受我们的产品及团队的时候,那么我们的价值也就产生了。


    当大家盲目赚钱的时候确忘了赚钱的目的何在了,假设有一天有足够多的钱、房、车的时候,这时候你想做的事情才是你真正喜欢的事情。看过《COCO》的应该都会明白一些存在的价值,当有更多的人记得你的时候,你就还活着。很多科学家,画家,音乐家虽然去世了,可是大家都还记得他们。我们不应该局限于将自己的技术急于变现而忘了身为一个设计师自身能够给社会带来的价值。我们有能力去创造价值超越于货币的价值,即使是慈善,那也是值得的。


    希望能够有更多的怪咖加入我们团队,能够一起去创造未来的产品。我们需要的技能有:软件开发,UI设计,原画,3D建模,特效制作,音频处理,信息安全等技术。

    我们主要涉及的领域:

    人工智能(AI)、增强现实(AR)、全息影像、机器人、信息安全

    关注我们的公众号:
    0_1540201941160_1540201844.png

    posted in GuaiK新闻 read more
  • G
    guluting

    特地的将prepareGeometryChange()拿出来说是因为它是一个很容易让人忽视掉的一个函数。
    用过QGraphicsItem类去绘图的应该都知道每个图元都是有一个矩形的轮廓的,通过在下列函数中设置

    QRectF QGraphicsItem::boundingRect() const{
        return QRectF(l, t, w, h);
    }
    

    我们再实际使用中的时候会经常去的改变图元的位置,因为你创建的图元不可能永远都是静态的(你可以直接贴个图片得了)
    我们会通过函数去绘制我们的图元:

    int g_left;    // 左边距参数
    void QGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
        Q_UNUSED(option);
        Q_UNUSED(widget);
        QColor color = QColor(0x00,0x00,0x00);
        color.setAlpha(50);
        painter->setPen(QPen(color,1));
        painter->setBrush(QColor(0xff,0xff,0xff));
        painter->setOpacity(1);
        painter->drawRect(g_left,t,w,h); 
    }
    

    我们可能会通过鼠标的位置去改变左边距的参数

    void CursorItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        if (event->buttons() == Qt::LeftButton) {
            g_left = event->pos().x();
            prepareGeometryChange();      # 请看这一句 这是重点
            QGraphicsScene::update();     # 伪代码,通知场景刷新图元
        }
    }
    

    prepareGeometryChange()的目的在于通知场景即将发生的变化,这样场景会去刷新图元的位置坐标,否则,场景将不会察觉到item的变化,结果也未知。为了避免一些未知异常的产生,每次在修改图片坐标或形状时,按照以下步骤进行:

    • 修改boundingRect中用到的参数数据(坐标)本例中的g_left。

    • 列表然后调用prepareGeometryChange()去通知scene即将发生变化。

    • 列表QGraphicsScene::update();强制让场景层刷新图元数据。

    posted in GuaiK实验室 read more
  • G
    guluting

    备份

    # -h:主机地址    -d:数据库名称
    # 该指令会在当前目录生成dump目录,数据库备份目录就在其中
    mongodump -h localhost:27017 -d [db_name]
    

    恢复

    # -h 主机地址    -d:数据库名称    最后跟上之前备份的数据库路径
    mongorestore -h localhost:27017 -d [db_name]  ./dump/[db_name]
    

    posted in GuaiK机房 read more