SharedPointer<ConnInfo> BaseProxy::get_Conn(){ SharedPointer<ConnInfo> conn; if (_use_existing_socket) { conn = ConnectionManager::get_instance()->get_connection(_name); } else { SharedPointer<BinaryProtocol> prot; bool ok=false; while(_protocols.get(prot, 10)==0&&!ok){ //deal CLOSE_WAIT connect if(prot.is_valid()&&prot->getTransport().is_valid()){ if((ok=SocketTool::is_ok(prot->getTransport()->id()))){ conn=SharedPointer<ConnInfo>(new(std::nothrow)ConnInfo(prot)); break; } } } if(!ok){ conn=create_Conn(); } } if (conn.is_valid() && conn->proto.is_valid() && conn->proto->getTransport().is_valid()) { int32_t tm = 0; if (get_property(PROXY_SEND_TIMEOUT, tm)) { SocketTool::set_sndtimeout(conn->proto->getTransport()->id(), tm); } if (get_property(PROXY_RECV_TIMEOUT, tm)) { SocketTool::set_rcvtimeout(conn->proto->getTransport()->id(), tm); } } return conn; }
int32_t ServiceManager::add_service(SharedPointer<IProcessor> processor) { BGCC_TRACE("bgcc", "ServiceManager::add_service"); std::string name; bool exist; if (processor.is_valid()) { name = processor->get_name(); } else { BGCC_NOTICE("bgcc", "Failed to add service, because param is NULL"); return -1; } Guard<Mutex> guard(&_mutex); if (!guard.is_locked()) { BGCC_WARN("bgcc", "Failed to lock mutex"); return -1; } exist = _name2service.find(name) != _name2service.end(); if (!exist) { std::pair<name2service_map::iterator, bool> v = _name2service.insert(std::make_pair(name, processor)); if (false == v.second) { return -1; } } return 0; }
/* * Class: bgcc_Transaction * Method: getCurrentTicketId * Signature: (Lbgcc/Protocol;ILjava/lang/String;)I */ JNIEXPORT jint JNICALL Java_bgcc_Transaction_getCurrentTicketId (JNIEnv *env, jobject transaction, jobject protocol, jint threadId, jstring fnName) { BGCC_TRACE("bgcc", "Transaction::getCurrentTicketId begin"); jclass transactionCls = env->GetObjectClass(transaction); jfieldID transactionAddressFid = env->GetFieldID(transactionCls, "transactionAddress", "J"); jclass protocolCls = env->GetObjectClass(protocol); jfieldID protocolAddressFid = env->GetFieldID(protocolCls, "protocolAddress", "J"); SharedPointer<IProtocol>* pProtocol = (SharedPointer<IProtocol>*)env->GetLongField(protocol, protocolAddressFid); if (!pProtocol || pProtocol->is_valid()) { BGCC_WARN("bgcc", "protocol is null"); return 0; } const char* pFnName = env->GetStringUTFChars(fnName, NULL); if (pFnName == NULL) { BGCC_WARN("bgcc", "Allocate fnName failed"); return 0; } Transaction* pTransaction = (Transaction*)env->GetLongField(transaction, transactionAddressFid); if (!pTransaction) { BGCC_WARN("bgcc", "transaction is null"); return 0; } int32_t ticketId = pTransaction->getCurrentTicketId(*pProtocol, (int32_t)threadId, pFnName); env->ReleaseStringUTFChars(fnName, pFnName); BGCC_TRACE("bgcc", "Transaction::getCurrentTicketId end\n"); return ticketId; }
int32_t ServiceManager::remove_service(SharedPointer<IProcessor> processor) { //NOTE: 本函数不用加锁 std::string name; if (processor.is_valid()) { name = processor->get_name(); } else { return -1; } return remove_service(name); }
/* * Class: bgcc_BaseProxy * Method: getTicketId * Signature: (Ljava/lang/String;Lbgcc/IntHolder;ZLbgcc/Protocol;Lbgcc/Protocol;)I */ JNIEXPORT jint JNICALL Java_bgcc_BaseProxy_getTicketId (JNIEnv *env, jobject baseProxy, jstring fnName, jobject ticketIdHolder, jboolean last, jobject inProtocol, jobject outProtocol) { jclass baseProxyCls = env->GetObjectClass(baseProxy); jfieldID proxyAddressFid = env->GetFieldID(baseProxyCls, "proxyAddress", "J"); BaseProxy* pBaseProxy = (BaseProxy*)env->GetLongField(baseProxy, proxyAddressFid); if (!pBaseProxy) { return -1; } const char* name_str = env->GetStringUTFChars(fnName, JNI_FALSE); int32_t ticketId = 0; jclass inProtocolCls = env->GetObjectClass(inProtocol); jfieldID inProtocolValueFid = env->GetFieldID(inProtocolCls, "protocolAddress", "J"); SharedPointer<BinaryProtocol>* pInProtocol = (SharedPointer<BinaryProtocol>*)env->GetLongField(inProtocol, inProtocolValueFid); if (!pInProtocol || !pInProtocol->is_valid()) { return -1; } jclass outProtocolCls = env->GetObjectClass(outProtocol); jfieldID outProtocolValueFid = env->GetFieldID(outProtocolCls, "protocolAddress", "J"); SharedPointer<IProtocol>* pOutProtocol = (SharedPointer<IProtocol>*)env->GetLongField(outProtocol, outProtocolValueFid); if (!pOutProtocol || !pOutProtocol->is_valid()) { return -1; } BGCC_TRACE("bgcc", "Before call C++ Interface __get_ticket_id"); pBaseProxy->__get_ticket_id(name_str, ticketId, last ? true : false, *pInProtocol, *pOutProtocol); BGCC_TRACE("bgcc", "End call C++ Interface __get_ticket_id: ticketId: %d", ticketId); jclass ticketIdHolderCls = env->GetObjectClass(ticketIdHolder); jfieldID ticketIdValueFid = env->GetFieldID(ticketIdHolderCls, "value", "I"); env->SetIntField(ticketIdHolder, ticketIdValueFid, ticketId); env->ReleaseStringUTFChars(fnName, name_str); return 0; }
SharedPointer<ConnInfo> BaseProxy::create_Conn(){ SharedPointer<bgcc::ClientSocket> client = SharedPointer<bgcc::ClientSocket>( new ClientSocket(_serverinfo.getIP(),_serverinfo.getPort())); if (client.is_valid()) { if(client->open()==0){ SharedPointer<BinaryProtocol> prot = SharedPointer<BinaryProtocol>(new bgcc::BinaryProtocol(client)); return SharedPointer<ConnInfo>(new ConnInfo(prot)); } } return SharedPointer<ConnInfo>(NULL); }
SharedPointer<ConnInfo> SSLBaseProxy::create_Conn(){ SharedPointer<bgcc::ClientSocket> client = SharedPointer<bgcc::SSLClientSocket>( new SSLClientSocket(_serverinfo.getIP(),_serverinfo.getPort())); if (client.is_valid()) { if(client->open()==0){ SharedPointer<BinaryProtocol> prot = SharedPointer<BinaryProtocol>(new bgcc::BinaryProtocol(client)); if(prot.is_valid()&& prot->getTransport().is_valid()){ int32_t tm=0; if(get_property(PROXY_SEND_TIMEOUT, tm)){ SocketTool::set_sndtimeout(prot->getTransport()->id(), tm); } if(get_property(PROXY_RECV_TIMEOUT, tm)){ SocketTool::set_rcvtimeout(prot->getTransport()->id(), tm); } } return SharedPointer<ConnInfo>(new ConnInfo(prot)); } } return SharedPointer<ConnInfo>(NULL); }
void* call_back_thread_func(void* param) { BGCC_TRACE("bgcc", "enroll self"); callback_thread_arg_t* arg = (callback_thread_arg_t*)param; std::string proxy_name = arg->proxy_name; std::string server_ip = arg->server_ip; int32_t server_port = arg->server_port; ServiceManager* service_manager = arg->service_manager; Semaphore* sema = arg->sema; SharedPointer<ClientSocket> connect; SharedPointer<BinaryProtocol> proto; #ifndef _WIN32 int32_t ep = epoll_create(1); struct epoll_event ee; struct epoll_event revents[1]; #endif RECON: sema->signal(); connect = SharedPointer<ClientSocket>( new(std::nothrow) ClientSocket(server_ip, server_port)); connect->open(); connect->set_recv_timeout(60*60*24*30); proto = SharedPointer<BinaryProtocol>( new(std::nothrow) BinaryProtocol(connect)); int32_t ret = 0; ret = proto->writeMessageBegin("bgcc::BaseProcessor_enroll", "__enroll", bgcc::CALL, 0); if (ret < 0) { bgcc::TimeUtil::safe_sleep_s(1); goto RECON; } ret = proto->writeString(proxy_name); if (ret < 0) { bgcc::TimeUtil::safe_sleep_s(1); goto RECON; } ret = proto->writeMessageEnd(); if (ret < 0) { bgcc::TimeUtil::safe_sleep_s(1); goto RECON; } #ifndef _WIN32 ee.data.fd = connect->get_socket(); ee.events = EPOLLIN; epoll_ctl(ep, EPOLL_CTL_ADD, connect->get_socket(), &ee); #endif while (true) { #ifndef _WIN32 int32_t nevent = epoll_wait(ep, revents, 1, -1); BGCC_TRACE("bgcc", "epoll_wait return %d", nevent); if (nevent >= 1) { #endif char buffer[BUFSIZ]; int32_t xxret; xxret = connect->read(buffer, 20); BGCC_TRACE("bgcc", "ret value read %d", xxret); if (0 != xxret) { #ifndef _WIN32 epoll_ctl(ep, EPOLL_CTL_DEL, connect->get_socket(), &ee); #endif bgcc::TimeUtil::safe_sleep_s(1); goto RECON; } int32_t body_len = (int32_t)ntohl(*(uint32_t*)(buffer +16)); BGCC_TRACE("bgcc", "body size %d", body_len); char body[BUFSIZ]; xxret = connect->read(body, body_len); BGCC_TRACE("bgcc", "body ret value read %d", xxret); if (0 != xxret) { #ifndef _WIN32 epoll_ctl(ep, EPOLL_CTL_DEL, connect->get_socket(), &ee); #endif bgcc::TimeUtil::safe_sleep_s(1); goto RECON; } int32_t processor_name_len = (int32_t)ntohl(*(uint32_t*)(body)); std::string processor_name(body + 4, processor_name_len); SharedPointer<IProcessor> processor = service_manager->get_service(processor_name); if (processor.is_valid()) { processor->process( body + 4 + processor_name_len, body_len - 4 - processor_name_len, proto); } /* added for handling unexist service*/ else { processor = service_manager->get_service("._baseservice_2012"); if (processor.is_valid()) { SharedPointer<BinaryProtocol> bp(new BinaryProtocol(SharedPointer<ITransport>(NULL))); bp->writeMessageBegin("xx", "__service_not_found", bgcc::CALL, 0); bp->writeInt32(0); bp->writeString("__service_not_found"); bp->writeBool(false); void* data = NULL; int32_t head_body_size; NBDataBuffer* db = bp->get_data_buffer(); db->get_data(&data, head_body_size); processor->process( (char*)data + 20 + 4 + 2, head_body_size - 20 - 4 - 2, proto); } } #ifndef _WIN32 } #endif } //#ifdef _WIN32 return NULL; //#endif }
void bgcc::BusizProcessor::ProcessUser(ReadItem *pItem, const std::string &name, void *param, bool ssl, void* arg) { BGCC_TRACE("bgcc", "...Enter User Process"); char *p= pItem->item.data; static char buffer[MAX_DEFAULT_LEN]={0}; int32_t buffer_size=MAX_DEFAULT_LEN; bgcc::ServiceManager* service_manager = NULL; bgcc::ThreadPool* thread_pool = NULL; SOCKET sock=INVALID_SOCKET; #ifndef _WIN32 TaskAsso *pT=(TaskAsso*)param; EpollServer* pServer=(EpollServer*)pT->pServer; service_manager = pServer->get_service_manager(); thread_pool = pServer->get_thread_pool(); sock=pT->event.fd; #endif SharedPointer<IProcessor> processor = service_manager->get_service(name); if(!processor.is_valid()){ processor = service_manager->get_service(DEF_SERVICE); if(processor.is_valid()){ p=NULL; if(Fake::fake_default_body(buffer, buffer_size)){ p=buffer; BGCC_WARN("bgcc", "...Cannot find processor %s to use default service", name.c_str()); } } } if (processor.is_valid() && p) { #ifndef _WIN32 if (ssl) { SSLEventCallback::RemoveFD(pT->pLoop, sock, false); } else { EventCallback::RemoveFD(pT->pLoop, sock, false); } #endif ServerPeerSocket* server_peer_socket = NULL; if (ssl) { #ifndef _WIN32 SSLEventCallbackArg* callbackArg = (SSLEventCallbackArg*)arg; server_peer_socket = new SSLServerPeerSocket(&(callbackArg->ssl), sock); #endif } else { server_peer_socket = new ServerPeerSocket(sock); } if (!server_peer_socket->GetPeerInfo().is_valid()) { BGCC_WARN("bgcc", "Broken socket, fd=%d", sock); return; } SharedPointer<ITransport> trans(server_peer_socket); SharedPointer<IProtocol> proto(new BinaryProtocol(trans)); SharedPointer<Runnable> task(new ServerTask(processor, p, (p==pItem->item.data?pItem->item.nread:buffer_size), proto, param)); if(!thread_pool->addTask(task)){ BGCC_WARN("bgcc", "...Add Task Failed(fd=%d, processor=%s)", sock, name.c_str()); } } else{ BGCC_WARN("bgcc", "...Cannot find Any Processor do nothing"); } BGCC_TRACE("bgcc", "...Leave User Process"); }
void bgcc::EventCallback::DataCallback(EventLoop* el, SOCKET fd, void* arg) { int32_t ret=0; char *p=NULL; bgcc::Mempool* mempool = bgcc::Mempool::get_instance(); bgcc::ReadItem *pItem=&(Items[fd]); reading_item_t& item = pItem->item; p = item.head_buf; if(S_SIZE_READING == item.state){ p = item.head_buf; } else if(S_DATA_READING == item.state){ p = item.data; } BGCC_TRACE("bgcc", "Enter DataCallback(fd=%d)", fd); while (true){ ret = recv(fd, p+item.nread, item.nexpected, 0); if(ret>0){ item.nread += ret; item.nexpected -= ret; if (0 == item.nexpected) { if (S_SIZE_READING == item.state) { if (item.head_buf[0] != 'b' || item.head_buf[1] != 'g' || item.head_buf[2] != 'c' || item.head_buf[3] != 'P') { BGCC_WARN("bgcc", "invalid bgcc header(fd=%d)", fd); pItem->err = -1; break; } item.state = S_DATA_READING; item.nexpected = BODY_LEN(p); if (item.nexpected < 0){ BGCC_WARN("bgcc", "Message body length=%d too short, remove from epoll", item.nexpected); break; } else if(0==item.nexpected){ BGCC_TRACE("bgcc", "Empty body Package"); break; } item.data = (char*)mempool->get_mem_block(item.nexpected); p = item.data; item.nread = 0; continue; } else if (S_DATA_READING == item.state) { pItem->err=0; break; } } } else if (ret<0) { if (SocketTool::is_interrupt()) { continue; } else if (SocketTool::is_wouldblock()) { return; } else { pItem->err=BgccSockGetLastError(); BGCC_WARN("bgcc", "Recv Failed. fd=%d errno=%d", fd, pItem->err); break; } } else{ pItem->err=-1; BGCC_TRACE("bgcc", "Recv Return 0. fd=%d ", fd); break; } } EpollServer *pArg=(EpollServer*)arg; TaskAsso *pT= (pArg?pArg->Tasks+fd:NULL); pT->pLoop=el; pT->pServer=(EpollServer*)arg; pT->pItem=pItem; PrepareEvent(pT->event, fd, arg); pItem->pTask=pT; int32_t todel=1; // save pItem->err and pItem->isEnroll // because pItem may be invalid after Process when err && isEnroll int32_t err = pItem->err; bool is_enroll = pItem->isEnroll; BusizProcessor::Process(pItem, pT, item.nread, &todel); if (err) { if (is_enroll) {//put_conn call RemoveFD, so here not to call RemoveFD if(todel){ BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); SharedPointer<BinaryProtocol> proto = SharedPointer<BinaryProtocol>( new BinaryProtocol( SharedPointer<ServerPeerSocket>( new ServerPeerSocket(fd) ))); SharedPointer<ConnInfo> info=SharedPointer<ConnInfo>( new ConnInfo(proto, pItem) ); if(proto.is_valid()&&info.is_valid()){ bgcc::ConnectionManager::get_instance()->put_connection(pItem->item.memo, info, true); } } } else{ BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); RemoveFD(el,fd); } } BGCC_TRACE("bgcc", "Leave DataCallback(fd=%d)", fd); }
void bgcc::SSLEventCallback::DataCallback(EventLoop* el, SOCKET fd, void* arg) { int32_t ret = 0; char* p = NULL; bgcc::Mempool* mempool = bgcc::Mempool::get_instance(); struct SSLEventCallbackArg* callbackArg = (struct SSLEventCallbackArg*)arg; bgcc::ReadItem* pItem = &(Items[fd]); reading_item_t& item = pItem->item; p = item.head_buf; if (S_SIZE_READING == item.state) { p = item.head_buf; } else if (S_DATA_READING == item.state) { p = item.data; } BGCC_TRACE("bgcc", "Enter SSL DataCallback(fd=%d)", fd); if (!callbackArg->ssl) { BGCC_TRACE("bgcc", "callbackArg->ssl is NULL, we should not be here."); TimeUtil::safe_sleep_ms(0); BGCC_TRACE("bgcc", "Leave SSL DataCallback(fd=%d)", fd); return; } bool do_while = true; while (true && do_while) { ret = SSL_read(callbackArg->ssl, p + item.nread, item.nexpected); switch(SSL_get_error(callbackArg->ssl, ret)) { case SSL_ERROR_NONE: item.nread += ret; item.nexpected -= ret; if (0 == item.nexpected) { if (S_SIZE_READING == item.state) { if (item.head_buf[0] != 'b' || item.head_buf[1] != 'g' || item.head_buf[2] != 'c' || item.head_buf[3] != 'P') { BGCC_WARN("bgcc", "invalid bgcc header(fd=%d)", fd); pItem->err = -1; do_while = false; break; } item.state = S_DATA_READING; item.nexpected = BODY_LEN(p); if (item.nexpected < 0) { BGCC_WARN("bgcc", "Message body length=%d too short, remove from epoll", item.nexpected); do_while = false; break; } else if (0 == item.nexpected) { BGCC_TRACE("bgcc", "Empty body Package"); do_while = false; break; } item.data = (char*)mempool->get_mem_block(item.nexpected); p = item.data; item.nread = 0; continue; } else if (S_DATA_READING == item.state) { pItem->err = 0; do_while = false; break; } } continue; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: return; default: pItem->err = -1; do_while = false; break; } } SSLEpollServer* pArg = (SSLEpollServer*)callbackArg->arg; TaskAsso* pT = pArg ? pArg->Tasks+fd : NULL; pT->pLoop = el; pT->pServer = pArg; pT->pItem = pItem; PrepareEvent(pT->event, fd, arg); pItem->pTask = pT; int32_t todel = 1; BusizProcessor::Process(pItem, pT, item.nread, &todel, true, arg); if (pItem->err) { SSL_shutdown(callbackArg->ssl); BGCC_DEBUG("bgcc", "Memory SSL free: %p", callbackArg->ssl); SSL_free(callbackArg->ssl); callbackArg->ssl = NULL; if (pItem->isEnroll) { if(todel){ BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); SharedPointer<BinaryProtocol> proto = SharedPointer<BinaryProtocol>( new BinaryProtocol( SharedPointer<ServerPeerSocket>( new ServerPeerSocket(fd) ))); SharedPointer<ConnInfo> info=SharedPointer<ConnInfo>( new ConnInfo(proto, pItem) ); if(proto.is_valid()&&info.is_valid()){ bgcc::ConnectionManager::get_instance()->put_connection(pItem->item.memo, info, true); } } } else { BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); RemoveFD(el,fd); } } BGCC_TRACE("bgcc", "Leave SSL DataCallback(fd=%d)", fd); }