int pyllbc_Service::RegisterCodec(int opcode, PyObject *codec) { if (_codec != This::BinaryCodec) { pyllbc_SetError("current codec strategy not BINARY, don't need register codec"); return LLBC_RTN_FAILED; } else if (_llbcSvcType == LLBC_IService::Raw) { pyllbc_SetError("RAW type service don't need register codec"); return LLBC_RTN_FAILED; } else if (!PyCallable_Check(codec)) { pyllbc_SetError("codec not callable"); return LLBC_RTN_FAILED; } if (!_codecs.insert(std::make_pair(opcode, codec)).second) { LLBC_String err; pyllbc_SetError(err.append_format( "repeat to register specify opcode's codec, opcode: %d", opcode)); return LLBC_RTN_FAILED; } Py_INCREF(codec); return LLBC_RTN_OK; }
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; }
int pyllbc_PackLemma_Dict::Write(pyllbc_Stream *stream, PyObject *values) { if (UNLIKELY(_state != Base::Done)) { pyllbc_SetError("could not pack not done dict-lemma"); return LLBC_RTN_FAILED; } if (!PyDict_Check(values)) { pyllbc_SetError("dict-lemma could not pack non-dict type object"); return LLBC_RTN_FAILED; } const Py_ssize_t len = PyDict_Size(values); LLBC_Stream &llbcStream = stream->GetLLBCStream(); #if _M_X64 llbcStream.WriteSInt32(static_cast<sint32>(len)); #else llbcStream.WriteSInt32(len); #endif Py_ssize_t pos = 0; PyObject *key, *value; while (PyDict_Next(values, &pos, &key, &value)) { if (_keyLemma->Write(stream, key) != LLBC_RTN_OK) return LLBC_RTN_FAILED; if (_valueLemma->Write(stream, value) != LLBC_RTN_OK) return LLBC_RTN_FAILED; } return LLBC_RTN_OK; }
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; }
PyObject *pyllbc_PackLemma_Dict::Read(pyllbc_Stream *stream) { if (UNLIKELY(_state != Base::Done)) { pyllbc_SetError("dict-lemma not done for unpack data"); return NULL; } int len; LLBC_Stream &llbcStream = stream->GetLLBCStream(); if (!llbcStream.ReadSInt32(len)) { pyllbc_SetError("not enough bytes to unpack dict data(head area)"); return NULL; } if (UNLIKELY(len < 0)) { pyllbc_SetError("when unpacking dict data, unpack len < 0"); return NULL; } PyObject *dict = PyDict_New(); for (int i = 0; i < len; i++) { PyObject *key = _keyLemma->Read(stream); if (!key) { Py_DECREF(dict); return NULL; } PyObject *value = _valueLemma->Read(stream); if (!value) { Py_DECREF(key); Py_DECREF(dict); return NULL; } if (PyDict_SetItem(dict, key, value) != 0) { Py_DECREF(value); Py_DECREF(key); Py_DECREF(dict); pyllbc_TransferPyError("when unpack dict data from stream"); return NULL; } Py_DECREF(value); Py_DECREF(key); } return dict; }
int pyllbc_PackLemma_Top::Write(pyllbc_Stream *stream, PyObject *values) { if (UNLIKELY(!this->IsDone())) { pyllbc_SetError("top-lemma not done, could not pack data"); return LLBC_RTN_FAILED; } const bool valuesIsNone = pyllbc_TypeDetector::IsNone(values); if (valuesIsNone) { if (!_lemmas.empty()) { pyllbc_SetError("not found any values to pack, but has been specified format character symbol"); return LLBC_RTN_FAILED; } return LLBC_RTN_OK; } else if (!pyllbc_TypeDetector::IsSequence(values)) { pyllbc_SetError("will pack data not iterable"); return LLBC_RTN_FAILED; } const Py_ssize_t seqSize = PySequence_Size(values); if (seqSize != static_cast<Py_ssize_t>(_lemmas.size())) { LLBC_String errStr; pyllbc_SetError(errStr.format( "will pack data sequence size[%ld] not equal format character size[%d]", seqSize, _lemmas.size())); return LLBC_RTN_FAILED; } for (Py_ssize_t i = 0; i < seqSize; i++) { Base *lemma = _lemmas.at(i); PyObject *obj = PySequence_GetItem(values, i); if (lemma->Write(stream, obj) != LLBC_RTN_OK) { Py_DECREF(obj); return LLBC_RTN_FAILED; } Py_DECREF(obj); } return LLBC_RTN_OK; }
int pyllbc_Service::Post(PyObject *callable) { if (!PyCallable_Check(callable)) { const LLBC_String objDesc = pyllbc_ObjUtil::GetObjStr(callable); pyllbc_SetError(LLBC_String().format("frame callable object not callable: %s", objDesc.c_str())); return LLBC_RTN_FAILED; } if (_handlingBeforeFrameCallables && _handlingAfterFrameCallables) { pyllbc_SetError("could not push callable object to service, internal error!"); return LLBC_RTN_FAILED; } if (_beforeFrameCallables.find(callable) != _beforeFrameCallables.end() || _afterFrameCallables.find(callable) != _afterFrameCallables.end()) { const LLBC_String objDesc = pyllbc_ObjUtil::GetObjStr(callable); pyllbc_SetError(LLBC_String().format( "repeat to add callable to service, callable: %s", objDesc.c_str())); return LLBC_RTN_FAILED; } Py_INCREF(callable); if (_handlingBeforeFrameCallables) { _afterFrameCallables.insert(callable); } else { if (!_handledBeforeFrameCallables) { _beforeFrameCallables.insert(callable); } else { if (!_handlingAfterFrameCallables) _afterFrameCallables.insert(callable); else _beforeFrameCallables.insert(callable); } } return LLBC_RTN_OK; }
int pyllbc_Service::Broadcast(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; if (this->SerializePyObj2Stream(data, stream) != LLBC_RTN_OK) { LLBC_XDelete(cLayerParts); return LLBC_RTN_FAILED; } // Send it. const void *bytes = stream.GetBuf(); const size_t len = stream.GetPos(); return _llbcSvc->Broadcast2(opcode, bytes, len, status, cLayerParts); }
PyObject *pyllbc_PackLemma_Top::Read(pyllbc_Stream *stream) { if (UNLIKELY(!this->IsDone())) { pyllbc_SetError("top-lemma not done, could not unpack data"); return NULL; } size_t idx = 0; PyObject *values = PyTuple_New(_lemmas.size()); for (; idx < _lemmas.size(); idx++) { PyObject *value; Base *lemma = _lemmas[idx]; if (!(value = lemma->Read(stream))) break; PyTuple_SET_ITEM(values, idx, value); } if (idx != _lemmas.size()) { Py_DECREF(values); values = NULL; } return values; }
int pyllbc_PackLemma_Top::Process(Symbol ch, Symbol nextCh) { _state = Base::Error; pyllbc_SetError("top level pack-lemma could not accept any character symbols"); return LLBC_RTN_FAILED; }
int pyllbc_Service::SerializePyObj2Stream(PyObject *pyObj, LLBC_Stream &stream) { if (_codec == This::JsonCodec) { std::string out; if (UNLIKELY(pyllbc_ObjCoder::Encode(pyObj, out) != LLBC_RTN_OK)) return LLBC_RTN_FAILED; stream.WriteBuffer(out.data(), out.size()); return LLBC_RTN_OK; } else { // Create python layer Stream instance. PyObject *arg = PyTuple_New(2); PyTuple_SetItem(arg, 0, PyInt_FromLong(0)); // stream init size = 0. Py_INCREF(pyObj); PyTuple_SetItem(arg, 1, pyObj); // initWrite = pyObj(steal reference). PyObject *pyStreamObj = PyObject_CallObject(This::_streamCls, arg); if (UNLIKELY(!pyStreamObj)) { Py_DECREF(arg); pyllbc_TransferPyError(); return LLBC_RTN_FAILED; } // Get cobj property. PyObject *cobj = PyObject_GetAttr(pyStreamObj, _keyCObj); if (UNLIKELY(!cobj)) { Py_DECREF(pyStreamObj); Py_DECREF(arg); pyllbc_SetError("could not get llbc.Stream property 'cobj'"); return LLBC_RTN_FAILED; } // Convert to pyllbc_Stream *. pyllbc_Stream *cstream = NULL; PyArg_Parse(cobj, "l", &cstream); // Let stream attach to inlStream. LLBC_Stream &inlStream = cstream->GetLLBCStream(); stream.Attach(inlStream); (void)inlStream.Detach(); stream.SetAttachAttr(false); Py_DECREF(cobj); Py_DECREF(pyStreamObj); Py_DECREF(arg); return LLBC_RTN_OK; } }
int pyllbc_PackLemma_Dict::Process(Base *lemma) { // Param check. if (!lemma->IsSerializable()) { _state = Base::Error; pyllbc_SetError("dict-lemma could not accept UnSerializable lemma"); return LLBC_RTN_FAILED; } // State check. if (_state == Base::Done || _state == Base::Error) { pyllbc_SetError("dict-lemma state is done or error, could not continuing to parse format string"); return LLBC_RTN_FAILED; } else if (_state == Base::Begin) { _state = Base::Error; pyllbc_SetError("dict-lemma expect dict begin character: '{', got lemma"); return LLBC_RTN_FAILED; } // Key, Value logic check. if (_valueLemma) { _state = Base::Error; pyllbc_SetError("dict-lemma expect dict close character'}', but got lemma"); return LLBC_RTN_FAILED; } else if (_keyLemma && !_gotKwSep) { _state = Base::Error; pyllbc_SetError("dict-lemma expect dict key-word separator':', but got lemma"); return LLBC_RTN_FAILED; } (!_keyLemma ? _keyLemma : _valueLemma) = lemma; _str.append(lemma->ToString()); return LLBC_RTN_OK; }
int pyllbc_Service::SetCodec(Codec codec) { if (codec != This::JsonCodec && codec != This::BinaryCodec) { pyllbc_SetError("invalid codec type", LLBC_ERROR_INVALID); return LLBC_RTN_FAILED; } else if (_started) { pyllbc_SetError("service already start, could not change codec strategy"); return LLBC_RTN_FAILED; } if (codec != _codec) _codec = codec; 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; }
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 pyllbc_ErrorHooker::Install() { if (_installed) { pyllbc_SetError(LLBC_ERROR_REENTRY); return LLBC_FAILED; } pyllbc_SetErrSetHock(new _SetDeleg(this, &This::Hook_ErrSet)); pyllbc_SetErrClearHook(new _ClearDeleg(this, &This::Hook_ErrClear)); _installed = true; return LLBC_OK; }
int pyllbc_ScriptIntegrator::Integrate() { if (_builded) return LLBC_RTN_OK; if (PyRun_SimpleString(_script.c_str()) != 0) { pyllbc_SetError(PYLLBC_ERROR_COMMON); return LLBC_RTN_FAILED; } _builded = true; return LLBC_RTN_OK; }
int pyllbc_PackLemma_Top::Process(Base *lemma) { if (!lemma->IsDone()) { _state = Base::Error; pyllbc_SetError("top level lemma could not accept not done lemma"); return LLBC_RTN_FAILED; } _state = Base::Accepting; _lemmas.push_back(lemma); _str.append(lemma->ToString()); return LLBC_RTN_OK; }
int pyllbc_Service::RegisterFacade(PyObject *facade) { if (!_facades.insert(facade).second) { PyObject *pyFacadeStr = PyObject_Str(facade); LLBC_String facadeStr = PyString_AsString(pyFacadeStr); Py_DECREF(pyFacadeStr); LLBC_String errStr; pyllbc_SetError(errStr.format("repeat to register facade: %s", facadeStr.c_str()), LLBC_ERROR_REPEAT); return LLBC_RTN_FAILED; } Py_INCREF(facade); return LLBC_RTN_OK; }
int pyllbc_Service::Start(int pollerCount) { if (_started) { pyllbc_SetError("service already started", LLBC_ERROR_REENTRY); return LLBC_RTN_FAILED; } _started = true; if (_llbcSvc->Start(pollerCount) != LLBC_RTN_OK) { _started = false; pyllbc_TransferLLBCError(__FILE__, __LINE__); return LLBC_RTN_FAILED; } return LLBC_RTN_OK; }
void pyllbc_ErrorHooker::TransferHookedErrorToPython() { if (_errCls && !PyErr_Occurred()) { _transfering = true; pyllbc_SetError(_errDesc, _llbcErrNo, _errCls); // Link the previous traceback, if we holded. if (_tbObj) { PyObject *errType, *errVal, *errTb; PyErr_Fetch(&errType, &errVal, &errTb); PyErr_NormalizeException(&errType, &errVal, &errTb); if (errTb == NULL) { errTb = _tbObj; } else { PyTracebackObject *perTb = reinterpret_cast<PyTracebackObject *>(errTb); while (perTb->tb_next) perTb = perTb->tb_next; perTb->tb_next = reinterpret_cast<PyTracebackObject *>(_tbObj); } _tbObj = NULL; PyErr_Restore(errType, errVal, errTb); } _transfering = false; Cleanup(); } }
int pyllbc_PackLemma_Dict::Process(Symbol ch, Symbol nextCh) { // State logic. if (_state == Base::Done && _state == Base::Error) { pyllbc_SetError("dict-lemma state is done or error, could not continuing to parse format string"); return LLBC_RTN_FAILED; } if (_state == Base::Begin) { if (ch != Base::DictBegin) { _state = Base::Error; pyllbc_SetError("dict-lemma expect dict begin character'{', got %c", ch); return LLBC_RTN_FAILED; } _state = Base::Accepting; _str.append(1, static_cast<char>(ch)); return LLBC_RTN_OK; } // Key-Word separator & dict close character('}') logic. if (ch == Base::DictKWSep) { if (!_keyLemma) { _state = Base::Error; pyllbc_SetError("dict-lemma expect key lemma, got key-word separator"); return LLBC_RTN_FAILED; } else if (_valueLemma) { _state = Base::Error; pyllbc_SetError("dict-lemma expect dict close character '}', got key-word separator"); return LLBC_RTN_FAILED; } _gotKwSep = true; _str.append(1, static_cast<char>(ch)); return LLBC_RTN_OK; } else if (ch == Base::DictEnd) { if (!_keyLemma || !_valueLemma) { _state = Base::Error; pyllbc_SetError("dict-lemma not done, but got dict close character '}'"); return LLBC_RTN_FAILED; } _state = Base::Done; _str.append(1, static_cast<char>(ch)); return LLBC_RTN_OK; } const SymbolGroup &raw = GroupedSymbol::Raw(); if (raw.find(ch) == raw.end()) { _state = Base::Error; pyllbc_SetError("dict-lemma could direct process non-raw type format character: %c", ch); return LLBC_RTN_FAILED; } Base *lemma = LLBC_New(pyllbc_PackLemma_Raw); if (lemma->Process(ch) != LLBC_RTN_OK) { delete lemma; _state = Base::Error; return LLBC_RTN_FAILED; } if (this->Process(lemma) != LLBC_RTN_OK) { delete lemma; return LLBC_RTN_FAILED; } return LLBC_RTN_OK; }
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; }