示例#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
SWINLINE swBuffer_trunk* swConnection_get_in_buffer(swConnection *conn)
{
	swBuffer_trunk *trunk = NULL;
	swBuffer *buffer;

	if (conn->in_buffer == NULL)
	{
		buffer = swBuffer_new(SW_BUFFER_SIZE);
		//buffer create failed
		if (buffer == NULL)
		{
			return NULL;
		}
		//new trunk
		trunk = swBuffer_new_trunk(buffer, SW_TRUNK_DATA, buffer->trunk_size);
		if (trunk == NULL)
		{
			sw_free(buffer);
			return NULL;
		}
		conn->in_buffer = buffer;
	}
	else
	{
		buffer = conn->in_buffer;
		trunk = buffer->tail;
		if (trunk == NULL || trunk->length == buffer->trunk_size)
		{
			trunk = swBuffer_new_trunk(buffer, SW_TRUNK_DATA, buffer->trunk_size);
		}
	}
	return trunk;
}
示例#3
0
int swFactory_end(swFactory *factory, int fd)
{
    swServer *serv = factory->ptr;
    swSendData _send;
    swDataHead info;

    bzero(&_send, sizeof(_send));
    _send.info.fd = fd;
    _send.info.len = 0;
    _send.info.type = SW_EVENT_CLOSE;

    swConnection *conn = swWorker_get_connection(serv, fd);
    if (conn == NULL || conn->active == 0)
    {
        //swWarn("can not close. Connection[%d] not found.", _send.info.fd);
        return SW_ERR;
    }
    else if (conn->close_force)
    {
        goto do_close;
    }
    else if (conn->closing)
    {
        swWarn("The connection[%d] is closing.", fd);
        return SW_ERR;
    }
    else if (conn->closed)
    {
        return SW_ERR;
    }
    else
    {
        do_close:
        conn->closing = 1;
        if (serv->onClose != NULL)
        {
            info.fd = fd;
            info.from_id =  conn->from_id;
            info.from_fd =  conn->from_fd;
            serv->onClose(serv, &info);
        }
        conn->closing = 0;
        conn->closed = 1;
        conn->close_errno = 0;

        if (swBuffer_empty(conn->out_buffer))
        {
            swReactor *reactor = &serv->reactor_threads[SwooleTG.id].reactor;
            return swReactorThread_close(reactor, conn->fd);
        }
        else
        {
            swBuffer_trunk *trunk = swBuffer_new_trunk(conn->out_buffer, SW_CHUNK_CLOSE, 0);
            trunk->store.data.val1 = _send.info.type;
            return SW_OK;
        }
    }
}
示例#4
0
文件: Buffer.c 项目: 4399data/swoole
/**
 * append to buffer queue
 */
int swBuffer_in(swBuffer *buffer, swSendData *send_data)
{
	swBuffer_trunk *trunk = swBuffer_new_trunk(buffer, SW_TRUNK_DATA, send_data->info.len);
	if (trunk == NULL)
	{
		return SW_ERR;
	}

	trunk->length = send_data->info.len;
	memcpy(trunk->data, send_data->data, trunk->length);

	swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|data_len=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, send_data->info.len,
			trunk->length, trunk);

	return SW_OK;
}
示例#5
0
文件: Buffer.c 项目: lzpfmh/swoole
/**
 * append to buffer queue
 */
int swBuffer_append(swBuffer *buffer, void *data, uint32_t size)
{
    swBuffer_trunk *chunk = swBuffer_new_trunk(buffer, SW_CHUNK_DATA, size);
    if (chunk == NULL)
    {
        return SW_ERR;
    }

    buffer->length += size;
    chunk->length = size;

    memcpy(chunk->store.ptr, data, size);

    swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|size=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, size,
            chunk->length, chunk);

    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
	}