Пример #1
0
SWINLINE swBuffer_trunk* swConnection_get_out_buffer(swConnection *conn, uint32_t type)
{
	swBuffer_trunk *trunk;
	if (conn->out_buffer == NULL)
	{
		conn->out_buffer = swBuffer_new(SW_BUFFER_SIZE);
		if (conn->out_buffer == NULL)
		{
			return NULL;
		}
	}
	if (type == SW_TRUNK_SENDFILE)
	{
		trunk = swBuffer_new_trunk(conn->out_buffer, SW_TRUNK_SENDFILE, 0);
	}
	else
	{
		trunk = swBuffer_get_trunk(conn->out_buffer);
		if (trunk == NULL)
		{
			trunk = swBuffer_new_trunk(conn->out_buffer, SW_TRUNK_DATA, conn->out_buffer->trunk_size);
		}
	}
	return trunk;
}
Пример #2
0
int swConnection_send_in_buffer(swConnection *conn)
{
	int ret;
#ifdef SW_DEBUG
    int i;
#endif

	swFactory *factory = SwooleG.factory;
	swEventData _send;
	swBuffer *buffer = conn->in_buffer;
	swBuffer_trunk *trunk = swBuffer_get_trunk(buffer);

	_send.info.fd = conn->fd;
	_send.info.type = (buffer->trunk_num == 1) ? SW_EVENT_TCP : SW_EVENT_PACKAGE_START;
	_send.info.from_id = conn->from_id;

	while (trunk != NULL)
	{
		_send.info.len = trunk->length;
		memcpy(_send.data, trunk->data, _send.info.len);
		ret = factory->dispatch(factory, &_send);

		//TODO: 处理数据失败,数据将丢失
		if (ret < 0)
		{
			swWarn("factory->dispatch failed.");
		}

		swBuffer_pop_trunk(buffer, trunk);
		trunk = swBuffer_get_trunk(buffer);

		swTrace("send2worker[i=%d][trunk_num=%d][type=%d]\n", i++, buffer->trunk_num, _send.info.type);

		if (_send.info.type == SW_EVENT_PACKAGE_START)
		{
			_send.info.type = SW_EVENT_PACKAGE_TRUNK;
		}
		//package end
		if (trunk == NULL || trunk->next == NULL)
		{
			_send.info.type = SW_EVENT_PACKAGE_END;
		}
	}
	return SW_OK;
}
Пример #3
0
/**
 * send buffer to client
 */
int swConnection_buffer_send(swConnection *conn)
{
	int ret, sendn;
	swBuffer *buffer = conn->out_buffer;
	swBuffer_trunk *trunk = swBuffer_get_trunk(buffer);
	sendn = trunk->length - trunk->offset;

	if (sendn == 0)
	{
		swBuffer_pop_trunk(buffer, trunk);
		return SW_CONTINUE;
	}
	ret = swConnection_send(conn, trunk->store.ptr + trunk->offset, sendn, 0);
	//printf("BufferOut: reactor=%d|sendn=%d|ret=%d|trunk->offset=%d|trunk_len=%d\n", reactor->id, sendn, ret, trunk->offset, trunk->length);
	if (ret < 0)
	{
		switch (swConnection_error(conn->fd, errno))
		{
		case SW_ERROR:
			swWarn("send to fd[%d] failed. Error: %s[%d]", conn->fd, strerror(errno), errno);
			return SW_OK;
		case SW_CLOSE:
			return SW_CLOSE;
		case SW_WAIT:
			return SW_WAIT;
		default:
			return SW_CONTINUE;
		}
	}
	//trunk full send
	else if(ret == sendn || sendn == 0)
	{
		swBuffer_pop_trunk(buffer, trunk);
	}
	else
	{
		trunk->offset += ret;
	}
	return SW_CONTINUE;
}
Пример #4
0
/**
 * send buffer to client
 */
int swBuffer_send(swBuffer *buffer, int fd)
{
	int ret, sendn;
	swBuffer_trunk *trunk = swBuffer_get_trunk(buffer);
	sendn = trunk->length - trunk->offset;

	if (sendn == 0)
	{
		swBuffer_pop_trunk(buffer, trunk);
		return SW_CONTINUE;
	}
	ret = send(fd, trunk->data + trunk->offset, sendn, 0);
	//printf("BufferOut: reactor=%d|sendn=%d|ret=%d|trunk->offset=%d|trunk_len=%d\n", reactor->id, sendn, ret, trunk->offset, trunk->length);
	if (ret < 0)
	{
		if (swConnection_error(fd, errno) < 0)
		{
			return SW_CLOSE;
		}
		else if(errno == EAGAIN)
		{
			return SW_WAIT;
		}
		else
		{
			swWarn("send to fd[%d] failed. Error: %s[%d]", fd, strerror(errno), errno);
			return SW_CONTINUE;
		}
	}
	//trunk full send
	else if(ret == sendn || sendn == 0)
	{
		swBuffer_pop_trunk(buffer, trunk);
	}
	else
	{
		trunk->offset += ret;
	}
	return SW_CONTINUE;
}
Пример #5
0
int swConnection_send_in_buffer(swConnection *conn)
{
	swFactory *factory = SwooleG.factory;
	swEventData _send;

	_send.info.fd = conn->fd;
	_send.info.from_id = conn->from_id;

#ifdef SW_USE_RINGBUFFER
	swServer *serv = SwooleG.serv;
	swMemoryPool *pool = serv->reactor_threads[conn->from_id].pool;
	swPackage package;

	package.length = 0;
	while (1)
	{
		package.data = pool->alloc(pool, buffer->length);
		if (package.data == NULL)
		{
			swYield();
			swWarn("reactor memory pool full.");
			continue;
		}
		break;
	}
	_send.info.type = SW_EVENT_PACKAGE;

	while (trunk != NULL)
	{
		_send.info.len = trunk->length;
		memcpy(package.data + package.length , trunk->data, trunk->length);
		package.length += trunk->length;

		swBuffer_pop_trunk(buffer, trunk);
		trunk = swBuffer_get_trunk(buffer);
	}
	_send.info.len = sizeof(package);
	memcpy(_send.data, &package, sizeof(package));
	//swWarn("[ReactorThread] copy_n=%d", package.length);
	return factory->dispatch(factory, &_send);

#else

	swBuffer *buffer = conn->in_buffer;
	swBuffer_trunk *trunk = swBuffer_get_trunk(buffer);

	int ret;
	_send.info.type = SW_EVENT_PACKAGE_START;

	/**
	 * lock target
	 */
	SwooleTG.factory_lock_target = 1;

	while (trunk != NULL)
	{
		_send.info.len = trunk->length;
		memcpy(_send.data, trunk->store.ptr, _send.info.len);
		//package end
		if (trunk->next == NULL)
		{
			_send.info.type = SW_EVENT_PACKAGE_END;
		}
		ret = factory->dispatch(factory, &_send);
		//TODO: 处理数据失败,数据将丢失
		if (ret < 0)
		{
			swWarn("factory->dispatch failed.");
		}
		swBuffer_pop_trunk(buffer, trunk);
		trunk = swBuffer_get_trunk(buffer);

		swTrace("send2worker[trunk_num=%d][type=%d]\n", buffer->trunk_num, _send.info.type);
	}
	/**
	 * unlock
	 */
	SwooleTG.factory_target_worker = -1;
	SwooleTG.factory_lock_target = 0;

#endif
	return SW_OK;
}
Пример #6
0
/**
 * send to client or append to out_buffer
 */
int swReactorThread_send(swEventData *resp)
{
	int buf_size, copy_n;
	swServer *serv = SwooleG.serv;
	swSendData send_data;
	swEvent closeFd;
	swBuffer_trunk *trunk;
	swTask_sendfile *task;

	swConnection *conn = swServer_get_connection(serv, resp->info.fd);
	swReactor *reactor = &(serv->reactor_threads[conn->from_id].reactor);

	//recv length=0, will close connection
	if (resp->info.len == 0)
	{
#ifdef SW_REACTOR_DIRECT_SEND
		close_fd:
#endif
		{
			closeFd.fd = resp->info.fd;
			closeFd.from_id = resp->info.from_id;
			closeFd.type = SW_EVENT_CLOSE;
			//printf("closeFd.fd=%d|from_id=%d\n", closeFd.fd, closeFd.from_id);
			swReactorThread_onClose(reactor, &closeFd);
		}
		return SW_OK;
	}
	//sendfile to client
	else if(resp->info.type == SW_EVENT_SENDFILE)
	{
		trunk = swConnection_get_out_buffer(conn, SW_TRUNK_SENDFILE);
		if (trunk == NULL)
		{
			swWarn("get out_buffer trunk failed.");
			return SW_ERR;
		}
		task = sw_malloc(sizeof(swTask_sendfile));
		if (task == NULL)
		{
			swWarn("malloc for swTask_sendfile failed.");
			//TODO: 回收这里的内存
			return SW_ERR;
		}
		bzero(task, sizeof(swTask_sendfile));
		int file_fd = open(resp->data, O_RDONLY);
		if (file_fd < 0)
		{
			swWarn("open file[%s] failed. Error: %s[%d]", task->filename, strerror(errno), errno);
			return SW_ERR;
		}
		struct stat file_stat;
		if (fstat(file_fd, &file_stat) < 0)
		{
			swWarn("swoole_async_readfile: fstat failed. Error: %s[%d]", strerror(errno), errno);
			return SW_ERR;
		}
		task->filesize = file_stat.st_size;
		task->fd = file_fd;
		trunk->data = (void *)task;
		reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ);
	}
	//send data
	else
	{
		send_data.data = resp->data;
		send_data.info.len = resp->info.len;
		send_data.info.from_id = resp->info.from_id;
		send_data.info.fd = resp->info.fd;

#ifdef SW_REACTOR_DIRECT_SEND
		if(!swBuffer_empty(conn->out_buffer))
		{
			trunk = swBuffer_get_trunk(conn->out_buffer);
#else
		{
			trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA);
#endif
			buf_size = conn->out_buffer->trunk_size - trunk->length;

#ifdef SW_REACTOR_DIRECT_SEND
			append_out_buffer:
#else
			//listen EPOLLOUT event
			reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ);
#endif
			do
			{
				copy_n =  (buf_size >= send_data.info.len) ? send_data.info.len : buf_size;
				memcpy(trunk->data, send_data.data, copy_n);
				send_data.data += copy_n;
				send_data.info.len -= copy_n;
				trunk->length += copy_n;
				buf_size += copy_n;

				//trunk is full, create new trunk
				if (trunk->length == conn->out_buffer->trunk_size)
				{
					//trunk no enough space, creating a new trunk
					trunk = swBuffer_new_trunk(conn->out_buffer, SW_TRUNK_DATA);
					if (trunk == NULL)
					{
						swWarn("append to out_buffer failed.");
						return SW_ERR;
					}
					buf_size = conn->out_buffer->trunk_size;
				}
			} while(send_data.info.len > 0);
		}
#ifdef SW_REACTOR_DIRECT_SEND
		else
		{
			//try send
			int ret = swWrite(send_data.info.fd, send_data.data, send_data.info.len);
			if (ret < 0)
			{
				//连接已被关闭
				if (errno == ECONNRESET || errno == EBADF)
				{
					goto close_fd;
				}
				swWarn("factory->onFinish failed.fd=%d|from_id=%d. Error: %s[%d]", resp->info.fd, resp->info.from_id, strerror(errno), errno);
			}
			//Did not finish, add to writable event callback
			else if(ret < resp->info.len)
			{
				trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA);
				send_data.data += ret;
				send_data.info.len -= ret;
				buf_size = conn->out_buffer->trunk_size;
				goto append_out_buffer;
			}
			//printf("[writer]pop.fd=%d|from_id=%d|data=%s\n", resp->info.fd, resp->info.from_id, resp->data);
		}
#endif
	}