Beispiel #1
0
void bgcc::SSLEventCallback::SSLAcceptCallback(EventLoop* el, SOCKET fd, void* arg)
{
	int ret;
	Event e;
	SSLEventCallbackArg* newCallbackArg = (SSLEventCallbackArg*)arg;

	BGCC_TRACE("bgcc", "Enter SSL SSLAcceptCallback(fd=%d)", fd);

	ret = SSL_accept(newCallbackArg->ssl);
	switch(SSL_get_error(newCallbackArg->ssl, ret)) {
		case SSL_ERROR_NONE:
			BGCC_TRACE("bgcc", "ERROR NONE");
			PrepareEvent(e, fd, newCallbackArg);

            if (el->del_event(&e) != 0 || el->add_event(&e) != 0) {
				SSL_shutdown(newCallbackArg->ssl);
				BGCC_DEBUG("bgcc", "Memory SSL free: %p", newCallbackArg->ssl);
				SSL_free(newCallbackArg->ssl);
				newCallbackArg->ssl = NULL;
				RemoveFD(el, fd, true);
				BGCC_TRACE("bgcc", "ssl add_event failed");
			}
			break;
		case SSL_ERROR_WANT_ACCEPT:
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_WRITE:
			BGCC_TRACE("bgcc", "WANT ACCPET");
			break;
		default:
			BGCC_TRACE("bgcc", "DEFAULT");
			SSL_shutdown(newCallbackArg->ssl);
			BGCC_DEBUG("bgcc", "Memory SSL free: %p", newCallbackArg->ssl);
			SSL_free(newCallbackArg->ssl);
			newCallbackArg->ssl = NULL;
			RemoveFD(el, fd, true);
			break;
	}

	BGCC_TRACE("bgcc", "Leave SSL SSLAcceptCallback(fd=%d)", fd);
}
Beispiel #2
0
/*!	Removes the file descriptor from the specified slot.
*/
static struct file_descriptor*
remove_fd(struct io_context* context, int fd)
{
	struct file_descriptor* descriptor = NULL;

	if (fd < 0)
		return NULL;

	mutex_lock(&context->io_mutex);

	if ((uint32)fd < context->table_size)
		descriptor = context->fds[fd];

	select_info* selectInfos = NULL;
	bool disconnected = false;

	if (descriptor != NULL)	{
		// fd is valid
		TFD(RemoveFD(context, fd, descriptor));

		context->fds[fd] = NULL;
		fd_set_close_on_exec(context, fd, false);
		context->num_used_fds--;

		selectInfos = context->select_infos[fd];
		context->select_infos[fd] = NULL;

		disconnected = (descriptor->open_mode & O_DISCONNECTED);
	}

	mutex_unlock(&context->io_mutex);

	if (selectInfos != NULL)
		deselect_select_infos(descriptor, selectInfos, true);

	return disconnected ? NULL : descriptor;
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}