Beispiel #1
0
void LLBC_PacketHeaderParts::CleanupPart(_Part &part)
{
    if (part.type == _PartTypes::StrType)
        LLBC_Delete(part.value.strVal);
    else if (part.type == _PartTypes::BytesType)
        LLBC_Delete(part.value.bytesVal);
}
Beispiel #2
0
int pyllbc_Service::PreSubscribe(int opcode, PyObject *preHandler, int flags)
{
    if (_started)
    {
        pyllbc_SetError("service already started", LLBC_ERROR_INITED);
        return LLBC_RTN_FAILED;
    }
    else if (_llbcSvcType == LLBC_IService::Raw && opcode != 0)
    {
        pyllbc_SetError("RAW type service could not pre-subscribe opcode != 0's packet", LLBC_ERROR_INVALID);
        return LLBC_RTN_FAILED;
    }

    pyllbc_PacketHandler *wrapHandler = LLBC_New1(pyllbc_PacketHandler, opcode);
    if (wrapHandler->SetHandler(preHandler) != LLBC_RTN_OK)
    {
        LLBC_Delete(wrapHandler);
        return LLBC_RTN_FAILED;
    }

    if (!_preHandlers.insert(std::make_pair(opcode, wrapHandler)).second)
    {
        LLBC_Delete(wrapHandler);

        LLBC_String err;
        pyllbc_SetError(err.format(
            "repeat to pre-subscribe opcode: %d, the opcode already pre-subscribed", opcode), LLBC_ERROR_REPEAT);

        return LLBC_RTN_FAILED;
    }

    _llbcSvc->PreSubscribe(opcode, _cppFacade, &pyllbc_Facade::OnDataPreReceived);

    return LLBC_RTN_OK;
}
Beispiel #3
0
void LLBC_IocpPoller::HandleEv_AsyncConn(LLBC_PollerEvent &ev)
{
    bool succeed = true;
    LLBC_String reason = "Success";
    do {
        LLBC_SocketHandle handle = LLBC_CreateTcpSocketEx();
        if (handle == LLBC_INVALID_SOCKET_HANDLE)
        {
            succeed = false;
            reason = LLBC_FormatLastError();
            break;
        }

        LLBC_Socket *socket = LLBC_New1(LLBC_Socket, handle);

        socket->SetNonBlocking();
        socket->SetPollerType(LLBC_PollerType::IocpPoller);
        if (socket->AttachToIocp(_iocp) != LLBC_OK)
        {
            LLBC_Delete(socket);

            succeed = false;
            reason = LLBC_FormatLastError();
            break;
        }

        LLBC_POverlapped ol = LLBC_New(LLBC_Overlapped);
        ol->opcode = LLBC_OverlappedOpcode::Connect;
        ol->sock = handle;
        if (socket->ConnectEx(ev.peerAddr, ol) != LLBC_OK &&
                LLBC_GetLastError() != LLBC_ERROR_PENDING)
        {
            LLBC_Delete(ol);
            LLBC_Delete(socket);

            succeed = false;
            reason = LLBC_FormatLastError();
            break;
        }

        socket->InsertOverlapped(ol);

        LLBC_AsyncConnInfo asyncInfo;
        asyncInfo.socket = socket;
        asyncInfo.peerAddr = ev.peerAddr;
        asyncInfo.sessionId = ev.sessionId;

        _connecting.insert(std::make_pair(handle, asyncInfo));
    } while (false);

    if (!succeed)
        _svc->Push(LLBC_SvcEvUtil::
                BuildAsyncConnResultEv(succeed, reason, ev.peerAddr));
}
Beispiel #4
0
void LLBC_SvcEvUtil::DestroyEvBlock(LLBC_MessageBlock *block)
{
    // Skip event type.
    block->ShiftReadPos(sizeof(int));

    LLBC_ServiceEvent *svcEv;
    block->Read(&svcEv, sizeof(LLBC_ServiceEvent *));

    LLBC_Delete(svcEv);
    LLBC_Delete(block);
}
Beispiel #5
0
bool LLBC_IocpPoller::HandleConnecting(int waitRet, LLBC_POverlapped ol, int errNo, int subErrNo)
{
    if (ol->opcode != LLBC_OverlappedOpcode::Connect)
        return false;

    _Connecting::iterator it = _connecting.find(ol->sock);
    LLBC_AsyncConnInfo &asyncInfo = it->second;

    LLBC_Socket *sock = asyncInfo.socket;
    sock->DeleteOverlapped(ol);

    if (waitRet == LLBC_OK)
    {
        sock->SetOption(SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
        SetConnectedSocketDftOpts(sock);

        _svc->Push(LLBC_SvcEvUtil::BuildAsyncConnResultEv(
            true, LLBC_StrError(LLBC_ERROR_SUCCESS), asyncInfo.peerAddr));

        AddSession(CreateSession(sock, asyncInfo.sessionId), false);
    }
    else
    {
        _svc->Push(LLBC_SvcEvUtil::BuildAsyncConnResultEv(
                false, LLBC_StrErrorEx(errNo, subErrNo), asyncInfo.peerAddr));
        LLBC_Delete(asyncInfo.socket);
    }

    _connecting.erase(it);
    return true;
}
Beispiel #6
0
int pyllbc_Service::UnifyPreSubscribe(PyObject *preHandler, int flags)
{
    if (_started)
    {
        pyllbc_SetError("service already started", LLBC_ERROR_INITED);
        return LLBC_RTN_FAILED;
    }

    pyllbc_PacketHandler *wrapHandler = LLBC_New1(pyllbc_PacketHandler, 0);
    if (wrapHandler->SetHandler(preHandler) != LLBC_RTN_OK)
    {
        LLBC_Delete(wrapHandler);
        return LLBC_RTN_FAILED;
    }

    if (_unifyPreHandler)
    {
        pyllbc_SetError("repeat to unify pre-subscribe packet");
        return LLBC_RTN_FAILED;
    }

    _unifyPreHandler = wrapHandler;
    _llbcSvc->UnifyPreSubscribe(_cppFacade, &pyllbc_Facade::OnDataUnifyPreReceived);

    return LLBC_RTN_OK;
}
Beispiel #7
0
void LLBC_IocpPoller::HandleEv_Monitor(LLBC_PollerEvent &ev)
{
    // Wait return value.
    const int waitRet = *reinterpret_cast<int *>(ev.un.monitorEv);

    // Overlapped pointer.
    int off = sizeof(int);
    LLBC_POverlapped ol = *reinterpret_cast<LLBC_POverlapped *>(ev.un.monitorEv + off);
    // Error No.
    off += sizeof(LLBC_POverlapped);
    int errNo = *reinterpret_cast<int *>(ev.un.monitorEv + off);
    // Sub-Error No.
    off += sizeof(int);
    int subErrNo = *reinterpret_cast<int *>(ev.un.monitorEv + off);

    LLBC_Free(ev.un.monitorEv);

    if (HandleConnecting(waitRet, ol, errNo, subErrNo))
        return;

    _Sockets::iterator it  = _sockets.find(ol->sock);
    if (UNLIKELY(it == _sockets.end()))
    {
        if (ol->acceptSock != LLBC_INVALID_SOCKET_HANDLE)
            LLBC_CloseSocket(ol->acceptSock);
        if (ol->data)
            LLBC_Delete(reinterpret_cast<LLBC_MessageBlock *>(ol->data));
        LLBC_Delete(ol);

        return;
    }

    LLBC_Session *session = it->second;
    if (waitRet == LLBC_FAILED)
    {
        session->OnClose(ol, LLBC_New2(LLBC_SessionCloseInfo, errNo, subErrNo));
    }
    else
    {
        if (session->IsListen())
            Accept(session, ol);
        else if (ol->opcode == LLBC_OverlappedOpcode::Send)
            session->OnSend(ol);
        else if (ol->opcode == LLBC_OverlappedOpcode::Receive)
            session->OnRecv(ol);
    }
}
int TestCase_Comm_LazyTask::Run(int argc, char *argv[])
{
    LLBC_PrintLine("service/lazy task test:");

    LLBC_IService *svc = LLBC_IService::Create(LLBC_IService::Normal);

    LazyClass *taskObj = LLBC_New(LazyClass);
    svc->Post(taskObj, &LazyClass::BeforeRun);

    svc->Start();

    LLBC_PrintLine("Press any key to exit...");
    getchar();

    LLBC_Delete(svc);
    LLBC_Delete(taskObj);

    return LLBC_OK;
}
Beispiel #9
0
int pyllbc_Service::Send(int sessionId, int opcode, PyObject *data, int status, PyObject *parts)
{
    // Started check.
    if (UNLIKELY(!this->IsStarted()))
    {
        pyllbc_SetError("service not start");
        return LLBC_RTN_FAILED;
    }

    // Build parts, if exists.
    LLBC_PacketHeaderParts *cLayerParts = NULL;
    if (parts && _llbcSvcType != LLBC_IService::Raw)
    {
        if (!(cLayerParts = this->BuildCLayerParts(parts)))
            return LLBC_RTN_FAILED;
    }

    // Serialize python layer 'data' object to stream.
    LLBC_Stream stream;
    const int ret = this->SerializePyObj2Stream(data, stream);
    if (UNLIKELY(ret != LLBC_RTN_OK))
    {
        LLBC_XDelete(cLayerParts);
        return LLBC_RTN_FAILED;
    }

    // Build packet & send.
    LLBC_Packet *packet = LLBC_New(LLBC_Packet);
    packet->Write(stream.GetBuf(), stream.GetPos());

    packet->SetSessionId(sessionId);
    if (_llbcSvcType != LLBC_IService::Raw)
    {
        packet->SetOpcode(opcode);
        packet->SetStatus(status);

        if (cLayerParts)
        {
            cLayerParts->SetToPacket(*packet);
            LLBC_Delete(cLayerParts);
        }
    }

    if (UNLIKELY(_llbcSvc->Send(packet) == LLBC_RTN_FAILED))
    {
        pyllbc_TransferLLBCError(__FILE__, __LINE__);
        return LLBC_RTN_FAILED;
    }

    return LLBC_RTN_OK;
}
Beispiel #10
0
int LLBC_Session::Send(LLBC_Packet *packet)
{
    LLBC_MessageBlock *block;
#if LLBC_CFG_COMM_USE_FULL_STACK
    if (_protoStack->Send(packet, block) != LLBC_RTN_OK)
#else
    if (_protoStack->SendRaw(packet, block) != LLBC_RTN_OK)
#endif
        return LLBC_RTN_FAILED;

    if (this->Send(block) != LLBC_RTN_OK)
    {
        LLBC_Delete(block);
        return LLBC_RTN_FAILED;
    }

    return LLBC_RTN_OK;
}
Beispiel #11
0
int LLBC_IService::SetPacketHeaderDescFactory(LLBC_IPacketHeaderDescFactory *factory)
{
    typedef LLBC_PacketHeaderDescAccessor _Accessor;

    if (!factory)
    {
        LLBC_SetLastError(LLBC_ERROR_INVALID);
        return LLBC_RTN_FAILED;
    }
    else if (_Accessor::GetHeaderDesc(false))
    {
        LLBC_SetLastError(LLBC_ERROR_REPEAT);
        return LLBC_RTN_FAILED;
    }

    _Accessor::SetPacketDesc(factory->Create());
    LLBC_Delete(factory);

    return LLBC_RTN_OK;
}
Beispiel #12
0
int pyllbc_Service::Subscribe(int opcode, PyObject *handler, int flags)
{
    if (_started)
    {
        pyllbc_SetError("service already started", LLBC_ERROR_INITED);
        return LLBC_RTN_FAILED;
    }
    else if (_llbcSvcType == LLBC_IService::Raw && opcode != 0)
    {
        pyllbc_SetError(LLBC_String().format(
            "RAW type service could not subscribe opcode[%d] != 0's packet", opcode), LLBC_ERROR_INVALID);
        return LLBC_RTN_FAILED;
    }

    _PacketHandlers::const_iterator it = _handlers.find(opcode);
    if (it != _handlers.end())
    {
        const LLBC_String handlerDesc = pyllbc_ObjUtil::GetObjStr(handler);

        LLBC_String err;
        err.append_format("repeat to subscribeopcode: %d:%s, ", opcode, handlerDesc.c_str());
        err.append_format("the opcode already subscribed by ");
        err.append_format("%s", it->second->ToString().c_str());

        pyllbc_SetError(err, LLBC_ERROR_REPEAT);

        return LLBC_RTN_FAILED;
    }

    pyllbc_PacketHandler *wrapHandler = LLBC_New1(pyllbc_PacketHandler, opcode);
    if (wrapHandler->SetHandler(handler) != LLBC_RTN_OK)
    {
        LLBC_Delete(wrapHandler);
        return LLBC_RTN_FAILED;
    }

    _handlers.insert(std::make_pair(opcode, wrapHandler));
    _llbcSvc->Subscribe(opcode, _cppFacade, &pyllbc_Facade::OnDataReceived);

    return LLBC_RTN_OK;
}
Beispiel #13
0
LLBC_PollerMonitor::~LLBC_PollerMonitor()
{
    Stop();
    LLBC_Delete(_deleg);
}
Beispiel #14
0
LLBC_PacketHeaderParts *pyllbc_Service::BuildCLayerParts(PyObject *pyLayerParts)
{
    // Python layer parts(dict type) convert rules describe:
    //   python type       c++ type
    // --------------------------
    //   int/long/bool -->   sint64
    //     float4/8    -->  float/double
    //   str/bytearray -->  LLBC_String

    if (!PyDict_Check(pyLayerParts))
    {
        pyllbc_SetError("parts instance not dict type");
        return NULL;
    }

    LLBC_PacketHeaderParts *cLayerParts = LLBC_New(LLBC_PacketHeaderParts);

    Py_ssize_t pos = 0;
    PyObject *key, *value;
    while (PyDict_Next(pyLayerParts, &pos, &key, &value)) // key & value are borrowed.
    {
        const int serialNo = static_cast<int>(PyInt_AsLong(key));
        if (UNLIKELY(serialNo == -1 && PyErr_Occurred()))
        {
            pyllbc_TransferPyError("When fetch header part serial no");
            LLBC_Delete(cLayerParts);

            return NULL;
        }

        // Value type check order:
        //   int->
        //     str->
        //       float->
        //         long->
        //           bool->
        //             bytearray->
        //               other objects
        if (PyInt_CheckExact(value))
        {
            const sint64 cValue = PyInt_AS_LONG(value);
            cLayerParts->SetPart<sint64>(serialNo, cValue);
        }
        else if (PyString_CheckExact(value))
        {
            char *strBeg;
            Py_ssize_t strLen;
            if (UNLIKELY(PyString_AsStringAndSize(value, &strBeg, &strLen) == -1))
            {
                pyllbc_TransferPyError("When fetch header part value");
                LLBC_Delete(cLayerParts);

                return NULL;
            }

            cLayerParts->SetPart(serialNo, strBeg, strLen);

        }
        else if (PyFloat_CheckExact(value))
        {
            const double cValue = PyFloat_AS_DOUBLE(value);
            cLayerParts->SetPart<double>(serialNo, cValue);
        }
        else if (PyLong_CheckExact(value))
        {
            const sint64 cValue = PyLong_AsLongLong(value);
            cLayerParts->SetPart<sint64>(serialNo, cValue);
        }
        else if (PyBool_Check(value))
        {
            const int pyBoolCheck = PyObject_IsTrue(value);
            if (UNLIKELY(pyBoolCheck == -1))
            {
                pyllbc_TransferPyError("when fetch header part value");
                LLBC_Delete(cLayerParts);

                return NULL;
            }

            cLayerParts->SetPart<uint8>(serialNo, pyBoolCheck);
        }
        else if (PyByteArray_CheckExact(value))
        {
            char *bytesBeg = PyByteArray_AS_STRING(value);
            Py_ssize_t bytesLen = PyByteArray_GET_SIZE(value);

            cLayerParts->SetPart(serialNo, bytesBeg, bytesLen);
        }
        else // Other types, we simple get the object string representations.
        {
            LLBC_String strRepr = pyllbc_ObjUtil::GetObjStr(value);
            if (UNLIKELY(strRepr.empty() && PyErr_Occurred()))
            {
                LLBC_Delete(cLayerParts);
                return NULL;
            }

            cLayerParts->SetPart(serialNo, strRepr.data(), strRepr.size());
        }
    }

    return cLayerParts;
}
int TestCase_Comm_SendBytes::Run(int argc, char *argv[])
{
    LLBC_PrintLine("Servie send bytes test:");
    if (argc < 5)
    {
        LLBC_PrintLine("argument error, eg: ./a [client/server] [normal/raw] ip port");
        return LLBC_FAILED;
    }

    FetchArgs(argc, argv);
    LLBC_IService *svc = LLBC_IService::Create(_svcType);

    TestFacade *facade = LLBC_New(TestFacade);
    svc->RegisterFacade(facade);

    svc->Subscribe(OPCODE, facade, &TestFacade::OnRecv);

    int sid = 0;
    if (_asClient)
    {
        sid = svc->Connect(_runIp.c_str(), _runPort);
        if (sid == 0)
        {
            LLBC_FilePrintLine(stderr, "connect to %s:%d failed, err: %s",
                _runIp.c_str(), _runPort, LLBC_FormatLastError());
            LLBC_Delete(svc);

            return LLBC_FAILED;
        }

        LLBC_PrintLine("server connect to %s:%d success", _runIp.c_str(), _runPort);
    }
    else
    {
        sid = svc->Listen(_runIp.c_str(), _runPort);
        if (sid == 0)
        {
            LLBC_FilePrintLine(stderr, "failed to listen on %s:%d, err: %s",
                _runIp.c_str(), _runPort, LLBC_FormatLastError());
            LLBC_Delete(svc);

            return LLBC_FAILED;
        }

        LLBC_PrintLine("server listen on %s:%d", _runIp.c_str(), _runPort);
    }

    svc->Start();

    if (_asClient)
    {
        LLBC_Packet *pkt = LLBC_New(LLBC_Packet);
        pkt->SetHeader(sid, OPCODE, 0);
        pkt->Write("Hello, world");
        pkt->Write(0);

        svc->Send(pkt);
    }

    LLBC_PrintLine("Press any key to continue...");
    getchar();

    LLBC_Delete(svc);

    return LLBC_OK;
}
Beispiel #16
0
int TestCase_Comm_Svc::Run(int argc, char *argv[])
{
    LLBC_PrintLine("Server/Client test:");
    if (argc < 5)
    {
        LLBC_PrintLine("argument error, eg: ./a [client/server] [normal/raw] ip port");
        return -1;
    }

    // Parse arguments.
    const char *ip = argv[3];
    const int port = LLBC_Str2Int32(argv[4]);
    const bool asClient = LLBC_String(argv[1]) == "client" ? true : false;
    LLBC_IService::Type svcType = 
        LLBC_String(argv[2]) == "normal" ? LLBC_IService::Normal : LLBC_IService::Raw;

    LLBC_PrintLine("Will start %s type service, service type: %s",
        asClient ? "CLIENT" : "SERVER",
        svcType == LLBC_IService::Normal ? "Normal" : "Raw");

    // Create service
    LLBC_IService *svc = LLBC_IService::Create(svcType);
    TestFacade *facade = LLBC_New(TestFacade);
    svc->RegisterFacade(facade);
    svc->Subscribe(OPCODE, facade, &TestFacade::OnDataArrival);
    svc->SuppressCoderNotFoundWarning();
    svc->Start(2);

    // Connect to server / Create listen session to wait client connect.
    int sessionId;
    if (!asClient)
    {
        LLBC_PrintLine("Will listening in %s:%d", ip, port);
        if ((sessionId = svc->Listen(ip, port)) == 0)
        {
            LLBC_PrintLine("Create session failed, reason: %s", LLBC_FormatLastError());
            LLBC_Delete(svc);

            return -1;
        }
    }
    else
    {
        // Client service, we create some clients to test service.
        int clientCount;
        const int pollerType = LLBC_PollerType::Str2Type(LLBC_CFG_COMM_POLLER_MODEL);
        if (pollerType == LLBC_PollerType::SelectPoller)
            clientCount = 50;
        else
            clientCount = 1024;

        LLBC_PrintLine("Create %d clients to test", clientCount);

        for (int i = 0; i < clientCount; i++)
        {
            const int sessionId = svc->Connect(ip, port);

            const int dataSize = 4096;
            char *data = LLBC_Malloc(char, dataSize);
            ::memset(data, 1, dataSize);

            LLBC_Packet *packet = LLBC_New(LLBC_Packet);
            packet->SetHeader(sessionId, OPCODE, 0);
            packet->Write(data, dataSize);

            LLBC_Free(data);

            svc->Send(packet);

            // Test unhandled packet(unsubscribe opcode).
            LLBC_Packet *unhandledPacket = LLBC_New(LLBC_Packet);
            unhandledPacket->SetHeader(sessionId, OPCODE + 10000, 0);
            unhandledPacket->Write("Hello World", 12);

            svc->Send(unhandledPacket);
        }
    }

    LLBC_PrintLine("Press any key to continue...");
    getchar();

    return 0;
}
Beispiel #17
0
LLBC_SamplerGroup::~LLBC_SamplerGroup()
{
    LLBC_STLHelper::DeleteContainer(*_samplers, false);
    LLBC_Delete(_samplers);
}