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); }
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; }
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)); }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
LLBC_PollerMonitor::~LLBC_PollerMonitor() { Stop(); LLBC_Delete(_deleg); }
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; }
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; }
LLBC_SamplerGroup::~LLBC_SamplerGroup() { LLBC_STLHelper::DeleteContainer(*_samplers, false); LLBC_Delete(_samplers); }