コード例 #1
0
ファイル: FactoryProcess.c プロジェクト: netbaby/swoole
int swFactoryProcess_end(swFactory *factory, swDataHead *event)
{
	swServer *serv = factory->ptr;
	swEvent ev;
	bzero(&ev, sizeof(swEvent));

	ev.fd = event->fd;
	/**
	 * length == 0, close the connection
	 */
	ev.len = 0;

	/**
	 * passive or initiative
	 */
	ev.type = event->type;

	swConnection *conn = swServer_get_connection(serv, ev.fd);
	if (conn == NULL || conn->active == 0)
	{
		swWarn("can not close. Connection[%d] not found.", ev.fd);
		return SW_ERR;
	}
	event->from_id = conn->from_id;
	return swFactoryProcess_finish(factory, (swSendData *)&ev);
}
コード例 #2
0
ファイル: ReactorThread.c プロジェクト: ZheYuan/swoole
int swServer_reactor_thread_onWrite(swReactor *reactor, swDataHead *ev)
{
	swServer *serv = SwooleG.serv;
	swConnection *conn = swServer_get_connection(serv, ev->fd);
	int ret, sendn;
	if (conn->output.send_file != NULL)
	{
		swTask_sendfile *task = conn->output.send_file;
		sendn = (task->filesize - task->offset > SW_SENDFILE_TRUNK) ? SW_SENDFILE_TRUNK : task->filesize - task->offset;
		ret = sendfile(ev->fd, task->fd, &task->offset, sendn);

		//swWarn("ret=%d|task->offset=%ld|sendn=%d|filesize=%ld", ret, task->offset, sendn, task->filesize);
		if (ret < 0)
		{
			swWarn("sendfile failed. Error: %s[%d]", strerror(errno), errno);
			return SW_ERR;
		}
		if (task->offset >= task->filesize)
		{
			reactor->set(reactor, ev->fd, SW_EVENT_TCP | SW_EVENT_READ);
			conn->output.send_file = NULL;
			close(task->fd);
			sw_free(task);
		}
	}
	return SW_OK;
}
コード例 #3
0
ファイル: ReactorThread.c プロジェクト: gz818/swoole
/**
 * close the connection
 */
int swReactorThread_onClose(swReactor *reactor, swEvent *event)
{
	swServer *serv = reactor->ptr;
	swConnection *conn = swServer_get_connection(serv, event->fd);
	if (conn != NULL && conn->active == 1)
	{
		swConnection_close(serv, event->fd, event->type == SW_EVENT_CLOSE ? 0 : 1);
	}
	return SW_OK;
}
コード例 #4
0
ファイル: Server.c プロジェクト: flashhtml5/gitswoolestudy
static int swServer_master_onClose(swReactor *reactor, swEvent *event)
{
	swServer *serv = reactor->ptr;
	swConnection *conn;
	int queue[SW_CLOSE_QLEN];

	int i, n, fd;
	n = serv->main_pipe.read(&serv->main_pipe, queue, sizeof(queue));

	if (n <= 0)
	{
		swWarn("[Master]main_pipe read failed. Error: %s[%d]", strerror(errno), errno);
		return SW_ERR;
	}

	for (i = 0; i < n / sizeof(int); i++)
	{
		fd = queue[i];
		conn = swServer_get_connection(serv, fd);

		if (serv->onMasterClose != NULL)
		{
			serv->onMasterClose(serv, fd, conn->from_id);
		}

		/**
		 * Reset maxfd, use for connection_list
		 */
		if (fd == swServer_get_maxfd(serv))
		{
			int find_max_fd = fd - 1;

			/**
			 * Find the new max_fd
			 */
			for (; serv->connection_list[find_max_fd].active == 0 && find_max_fd > swServer_get_minfd(serv); find_max_fd--);
			swServer_set_maxfd(serv, find_max_fd);

			swTrace("set_maxfd=%d|close_fd=%d", find_max_fd, fd);
		}
	}
	return SW_OK;
}
コード例 #5
0
ファイル: test_server.c プロジェクト: Angel-fund/swoole
int my_onReceive(swFactory *factory, swEventData *req)
{
	int ret;
	char resp_data[SW_BUFFER_SIZE];
	swServer *serv = factory->ptr;


	swSendData resp;
	g_receive_count ++;
	memcpy(&resp.info, &req->info, sizeof(resp.info));

	resp.info.len = req->info.len + 8;
	req->data[req->info.len] = 0;

	snprintf(resp_data, resp.info.len, "Server:%s", req->data);
	resp.data = resp_data;
	ret = factory->finish(factory, &resp);
	if (ret < 0)
	{
		printf("send to client fail.errno=%d\n", errno);
	}
	if (req->info.from_id >= serv->reactor_num)
	{
		struct in_addr addr;
		addr.s_addr = req->info.fd;


		printf("onReceive[%d]: ip=%s|port=%d Data=%s|Len=%d\n", g_receive_count,
					inet_ntoa(addr), req->info.from_id,
					rtrim(req->data, req->info.len), req->info.len);
	}
	else
	{
		swConnection *conn = swServer_get_connection(serv, req->info.fd);
		printf("onReceive[%d]: ip=%s|port=%d Data=%s|Len=%d\n", g_receive_count,
					inet_ntoa(conn->addr.sin_addr), conn->addr.sin_port,
					rtrim(req->data, req->info.len), req->info.len);
	}
//	req->info.type = 99;
//	factory->event(factory, g_controller_id, req);
	return SW_OK;
}
コード例 #6
0
ファイル: FactoryProcess.c プロジェクト: amphisbe/swoole
/**
 * Worker进程,向writer发送数据
 */
int swFactoryProcess_finish(swFactory *factory, swSendData *resp)
{
	//UDP直接在worker进程内发送
	int ret, sendn, count, pipe_i;
	swFactoryProcess *object = factory->object;
	swServer *serv = factory->ptr;
	swReactor *reactor;
	int fd = resp->info.fd;

	//UDP在worker进程中直接发送到客户端
	if(resp->info.type == SW_EVENT_UDP)
	{
		ret = swServer_send_udp_packet(serv, resp);
		goto finish;
	}

	//swQueue_data for msg queue
	struct
	{
		long pti;
		swEventData _send;
	} sdata;

	//写队列mtype
	sdata.pti = (SwooleWG.id % serv->writer_num) + 1;

	//copy
	memcpy(sdata._send.data, resp->data, resp->info.len);

	swConnection *conn = swServer_get_connection(serv, fd);
	if(conn == NULL)
	{
		swWarn("connection[%d] not found.", fd);
		return SW_ERR;
	}

	sdata._send.info.fd = fd;
	sdata._send.info.type = resp->info.type;
	sdata._send.info.len = resp->info.len;
	sdata._send.info.from_id = conn->from_id;
	sendn = resp->info.len + sizeof(resp->info);

	//swWarn("send: type=%d|content=%s", resp->info.type, resp->data);
	swTrace("[Worker]wt_queue[%ld]->in| fd=%d", sdata.pti, fd);

	for (count = 0; count < SW_WORKER_SENDTO_COUNT; count++)
	{
#if SW_WORKER_IPC_MODE == 2
		ret = object->wt_queue.in(&object->wt_queue, (swQueue_data *)&sdata, sendn);
#else
		reactor = &(serv->reactor_threads[conn->from_id].reactor);
		if (serv->reactor_pipe_num > 1)
		{
			pipe_i = fd % serv->reactor_pipe_num + reactor->id;
		}
		else
		{
			pipe_i = reactor->id;
		}
		//swWarn("send to reactor. fd=%d|pipe_i=%d|reactor_id=%d|reactor_pipe_num=%d", fd, pipe_i, conn->from_id, serv->reactor_pipe_num);
		ret = write(object->workers[pipe_i].pipe_worker, &sdata._send, sendn);
#endif
		//printf("wt_queue->in: fd=%d|from_id=%d|data=%s|ret=%d|errno=%d\n", sdata._send.info.fd, sdata._send.info.from_id, sdata._send.data, ret, errno);
		if (ret >= 0)
		{
			break;
		}
		else if (errno == EINTR)
		{
			continue;
		}
		else if (errno == EAGAIN)
		{
			swYield();
		}
		else
		{
			break;
		}
	}
	finish:
	if (ret < 0)
	{
		swWarn("[Worker#%d]sendto writer pipe or queue failed. Error: %s [%d]", getpid(), strerror(errno), errno);
	}
	return ret;
}
コード例 #7
0
ファイル: Connection.c プロジェクト: woyear/swoole
/**
 * close connection
 */
SWINLINE void swConnection_close(swServer *serv, int fd, int notify)
{
	swConnection *conn = swServer_get_connection(serv, fd);
	swReactor *reactor;
	swEvent notify_ev;

	if(conn == NULL)
	{
		swWarn("[Master]connection not found. fd=%d|max_fd=%d", fd, swServer_get_maxfd(serv));
		return;
	}

	conn->active = 0;

	int reactor_id = conn->from_id;

	swCloseQueue *queue = &serv->reactor_threads[reactor_id].close_queue;

	//将关闭的fd放入队列
	queue->events[queue->num] = fd;
	//增加计数
	queue->num ++;

	reactor = &(serv->reactor_threads[reactor_id].reactor);
	swTrace("Close Event.fd=%d|from=%d", fd, reactor_id);

	//释放缓存区占用的内存
	if (serv->open_eof_check == 1)
	{
		if (conn->in_buffer != NULL)
		{
			swBuffer_free(conn->in_buffer);
			conn->in_buffer = NULL;
		}
	}
	else if (serv->open_length_check == 1)
	{
		if (conn->object != NULL)
		{
			swString_free(conn->object);
		}
	}

	if (conn->out_buffer != NULL)
	{
		swBuffer_free(conn->out_buffer);
		conn->out_buffer = NULL;
	}

	if (conn->in_buffer != NULL)
	{
		swBuffer_free(conn->in_buffer);
		conn->in_buffer = NULL;
	}

	//通知到worker进程
	if (serv->onClose != NULL && notify == 1)
	{
		//通知worker进程
		notify_ev.from_id = reactor_id;
		notify_ev.fd = fd;
		notify_ev.type = SW_EVENT_CLOSE;
		SwooleG.factory->notify(SwooleG.factory, &notify_ev);
	}

	//通知主进程
	if (queue->num == SW_CLOSE_QLEN)
	{
		swReactorThread_close_queue(reactor, queue);
	}

#ifdef SW_SOCKET_SET_LINGER
	struct linger linger;
	linger.l_onoff = 0;
	linger.l_linger = 0;

	if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)) == -1)
	{
		swWarn("setsockopt(SO_LINGER) failed. Error: %s[%d]", strerror(errno), errno);
	}
#endif

	//关闭此连接,必须放在最前面,以保证线程安全
	reactor->del(reactor, fd);
}
コード例 #8
0
ファイル: FactoryProcess.c プロジェクト: adrianolee/swoole
/**
 * worker: send to client
 */
int swFactoryProcess_finish(swFactory *factory, swSendData *resp)
{
	int ret, sendn, count;
	swFactoryProcess *object = factory->object;
	swServer *serv = factory->ptr;
	int fd = resp->info.fd;

	//unix dgram
	if (resp->info.type == SW_EVENT_UNIX_DGRAM)
	{
		socklen_t len;
		struct sockaddr_un addr_un;
		int from_sock = resp->info.from_fd;

		addr_un.sun_family = AF_UNIX;
		memcpy(addr_un.sun_path, resp->sun_path, resp->sun_path_len);
		len = sizeof(addr_un);
		ret = swSendto(from_sock, resp->data, resp->info.len, 0, (struct sockaddr *) &addr_un, len);
		goto finish;
	}
	//UDP pacakge
	else if (resp->info.type == SW_EVENT_UDP || resp->info.type == SW_EVENT_UDP6)
	{
		ret = swServer_send_udp_packet(serv, resp);
		goto finish;
	}

	//swQueue_data for msg queue
	struct
	{
		long pti;
		swEventData _send;
	} sdata;

	//for message queue
	sdata.pti = (SwooleWG.id % serv->writer_num) + 1;

	//copy
	memcpy(sdata._send.data, resp->data, resp->info.len);

	swConnection *conn = swServer_get_connection(serv, fd);
	if (conn == NULL || conn->active == 0)
	{
		swWarn("connection[%d] not found.", fd);
		return SW_ERR;
	}

	sdata._send.info.fd = fd;
	sdata._send.info.type = resp->info.type;
	sdata._send.info.len = resp->info.len;
	sdata._send.info.from_id = conn->from_id;
	sendn = resp->info.len + sizeof(resp->info);

	//swWarn("send: type=%d|content=%s", resp->info.type, resp->data);
	swTrace("[Worker]wt_queue[%ld]->in| fd=%d", sdata.pti, fd);

	for (count = 0; count < SW_WORKER_SENDTO_COUNT; count++)
	{
		if (serv->ipc_mode == SW_IPC_MSGQUEUE)
		{
			ret = object->wt_queue.in(&object->wt_queue, (swQueue_data *)&sdata, sendn);
		}
		else
		{
			int pipe_i;
			swReactor *reactor = &(serv->reactor_threads[conn->from_id].reactor);
			if (serv->reactor_pipe_num > 1)
			{
				pipe_i = fd % serv->reactor_pipe_num + reactor->id;
			}
			else
			{
				pipe_i = reactor->id;
			}
			//swWarn("send to reactor. fd=%d|pipe_i=%d|reactor_id=%d|reactor_pipe_num=%d", fd, pipe_i, conn->from_id, serv->reactor_pipe_num);
			ret = write(object->workers[pipe_i].pipe_worker, &sdata._send, sendn);
		}
		//printf("wt_queue->in: fd=%d|from_id=%d|data=%s|ret=%d|errno=%d\n", sdata._send.info.fd, sdata._send.info.from_id, sdata._send.data, ret, errno);
		if (ret >= 0)
		{
			break;
		}
		else if (errno == EINTR)
		{
			continue;
		}
		else if (errno == EAGAIN)
		{
			swYield();
		}
		else
		{
			break;
		}
	}
	finish:
	if (ret < 0)
	{
		swWarn("[Worker#%d]sendto writer pipe or queue failed. Error: %s [%d]", getpid(), strerror(errno), errno);
	}
	return ret;
}
コード例 #9
0
ファイル: ReactorThread.c プロジェクト: ZheYuan/swoole
int swReactorThread_response(swEventData *resp)
{
	int ret;
	swServer *serv = SwooleG.serv;
	swFactory *factory = SwooleG.factory;
	swReactor *reactor;
	swSendData send_data;
	swDataHead closeFd;

	//表示关闭
	if (resp->info.len == 0)
	{
		close_fd:
		{
			closeFd.fd = resp->info.fd;
			closeFd.from_id = resp->info.from_id;
			closeFd.type = SW_EVENT_CLOSE;
			reactor = &(serv->reactor_threads[closeFd.from_id].reactor);
			//printf("closeFd.fd=%d|from_id=%d\n", closeFd.fd, closeFd.from_id);
			swServer_reactor_thread_onClose(reactor, &closeFd);
		}
		return SW_OK;
	}
	//发送文件
	else if(resp->info.type == SW_EVENT_SENDFILE)
	{
		swConnection *conn = swServer_get_connection(serv, resp->info.fd);
		conn->output.send_file = sw_malloc(sizeof(swTask_sendfile));
		if (conn->output.send_file == NULL)
		{
			swWarn("malloc for swTask_sendfile failed.");
			return SW_ERR;
		}
		bzero(conn->output.send_file, sizeof(swTask_sendfile));
		int file_fd = open(resp->data, O_RDONLY);
		if (file_fd < 0)
		{
			swWarn("open file[%s] failed. Error: %s[%d]", send_data.data, 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;
		}
		conn->output.send_file->filesize = file_stat.st_size;
		conn->output.send_file->fd = file_fd;
		reactor = &(serv->reactor_threads[closeFd.from_id].reactor);
		reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ);
	}
	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;
		ret = factory->onFinish(factory, &send_data);
		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);
		}
		//printf("[writer]pop.fd=%d|from_id=%d|data=%s\n", resp->info.fd, resp->info.from_id, resp->data);
	}
	return SW_OK;
}
コード例 #10
0
ファイル: ReactorThread.c プロジェクト: gz818/swoole
/**
 * 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
	}
コード例 #11
0
ファイル: Server.c プロジェクト: flashhtml5/gitswoolestudy
		}
		else
		{
			_send.info.len = length;
			_send.length = 0;
		}
		return factory->finish(factory, &_send);
	}
#else
	else
	{
		char buffer[SW_BUFFER_SIZE];
		int trunk_num = (length / SW_BUFFER_SIZE) + 1;
		int send_n = 0, i, ret;

		swConnection *conn = swServer_get_connection(serv, fd);
		if (conn == NULL || conn->active == 0)
		{
			swWarn("Connection[%d] has been closed.", fd);
			return SW_ERR;
		}

		for (i = 0; i < trunk_num; i++)
		{
			//last chunk
			if (i == (trunk_num - 1))
			{
				send_n = length % SW_BUFFER_SIZE;
				if (send_n == 0)
					break;
			}