Exemple #1
0
void IRC::disconnect() {
    if(connected) {
        fast_write("QUIT");
        delete socket; //same effect
        connected = false;
    }
}
Exemple #2
0
int main(int argc, char **argv)
{
	liao_log("liao_server", LOG_PID|LOG_NDELAY, LOG_MAIL);

	if (argc != 3) {
		usage(argv[0]);
		exit(0);
	}

	if (chdir(LIAO_HOME) == -1) {
		log_alert("cannot start: unable to switch to home directory");	
		exit(0);
	}

	snprintf(msg_id, sizeof(msg_id), "00000000");
	
	char cfg_file[MAX_LINE] = CFG_FILE;
	
	int c;
	const char *args = "c:h";
	while ((c = getopt(argc, argv, args)) != -1) {
		switch (c) {
			case 'c':
				snprintf(cfg_file, sizeof(cfg_file), "%s", optarg);
				break;
				
			case 'h':
			default:
				usage(argv[0]);
				exit(0);
		}
	}

	// 处理配置文件 
	if (conf_init(cfg_file)) {
		fprintf(stderr, "Unable to read control files:%s\n", cfg_file);
		log_error("Unable to read control files:%s", cfg_file);
		exit(1);
	}

	/*	
	// 检查队列目录
	if (strlen(config_st.queue_path) <= 0) {
		fprintf(stderr, "Unable to read queue path.\n");
		log_error("Unable to read queue path.");
		exit(1);
	}
	if ( access(config_st.queue_path, F_OK) ) {
		fprintf(stderr, "Queue path:%s not exists:%s, so create it.\n", config_st.queue_path, strerror(errno));	
		log_error("Queue path:%s not exists:%s, so create it.", config_st.queue_path, strerror(errno));	

		umask(0);
		mkdir(config_st.queue_path, 0777);
	}*/
	

	online_d = dictionary_new(atoi(config_st.max_works) + 1);
	

	child_st = (struct childs *)malloc((atoi(config_st.max_works) + 1) * sizeof(struct childs));
	if (!child_st) {
		log_error("malloc childs [%d] failed:[%d]%s", (atoi(config_st.max_works) + 1), errno, strerror(errno));
		exit(1);
	}
	
	int i = 0;
	for (i=0; i<(atoi(config_st.max_works) + 1); i++) {
		child_st[i].used = 0;
		child_st[i].pid = -1;
		child_st[i].client_fd = -1;
		child_st[i].pipe_r_in = -1;
		child_st[i].pipe_r_out = -1;
		child_st[i].pipe_w_in = -1;
		child_st[i].pipe_w_out = -1;
		memset(child_st[i].mid, 0, sizeof(child_st[i].mid));
		child_st[i].mfp_out = NULL;
	}

	// 开始服务
	int connfd, epfd, sockfd, n, nread;
	struct sockaddr_in local, remote;
	socklen_t addrlen;

	// 初始化buffer
	char buf[BUF_SIZE];

	size_t pbuf_len = 0;
	size_t pbuf_size = BUF_SIZE + 1;
	char *pbuf = (char *)calloc(1, pbuf_size);
	if (pbuf == NULL) {
		log_error("calloc fail: size[%d]", pbuf_size);
		exit(1);
	}

	// 创建listen socket
	int bind_port = atoi(config_st.bind_port);
	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		log_error("socket failed:[%d]:%s", errno, strerror(errno));
		exit(1);
	}
	if (setnonblocking(listenfd) > 0) {
		exit(1);
	}

	bzero(&local, sizeof(local));
	local.sin_family = AF_INET;
	local.sin_addr.s_addr = htonl(INADDR_ANY);
	local.sin_port = htons(bind_port);
	if (bind(listenfd, (struct sockaddr *)&local, sizeof(local)) < 0) {
		log_error("bind local %d failed:[%d]%s", bind_port, errno, strerror(errno));
		exit(1);
	}
	log_info("bind local %d succ", bind_port);

	if (listen(listenfd, atoi(config_st.max_works)) != 0) {
		log_error("listen fd[%d] max_number[%d] failed:[%d]%s", listenfd, atoi(config_st.max_works), errno, strerror(errno));
		exit(1);
	}
	
	// 忽略pipe信号 
	sig_pipeignore();
	// 捕抓子进程退出信号
	sig_catch(SIGCHLD, sigchld);

	// epoll create fd
	epoll_event_num = atoi(config_st.max_works) + 1;
	epoll_evts = NULL;
	epoll_fd = -1;
	epoll_nfds = -1;

	int epoll_i = 0;

	epoll_evts = (struct epoll_event *)malloc(epoll_event_num * sizeof(struct epoll_event));
	if (epoll_evts == NULL) {
		log_error("alloc epoll event failed");
    	_exit(111);
    }

	epoll_fd = epoll_create(epoll_event_num);
	if (epoll_fd == -1) {
		log_error("epoll_create max_number[%d] failed:[%d]%s", epoll_event_num, errno, strerror(errno));
		exit(1);
	}

	struct epoll_event ev;
	ev.events = EPOLLIN;
	ev.data.fd = listenfd;
	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) {
		log_error("epoll_ctl: listen_socket failed:[%d]%s", errno, strerror(errno));
		exit(1);
	}
	epoll_num_running = 1;

	for (;;) {

		epoll_nfds = epoll_wait(epoll_fd, epoll_evts, epoll_event_num, -1);
		
		if (epoll_nfds == -1) {
			if (errno == EINTR)	{
				// 收到中断信号
				log_info("epoll_wait recive EINTR signal, continue");
				continue;
			}

			_exit(111);
		}

		log_debug("epoll_num_running:%d nfds:%d", epoll_num_running, epoll_nfds);
		for (epoll_i = 0; epoll_i < epoll_nfds; epoll_i++) {
			sig_childblock();

			int evt_fd = epoll_evts[epoll_i].data.fd;
			if (evt_fd == listenfd) {
				if ((connfd = accept(listenfd, (struct sockaddr *) &remote, &addrlen)) > 0) {
					char *ipaddr = inet_ntoa(remote.sin_addr);
					log_info("accept client:%s", ipaddr);
					
					char greetting[512] = {0};
					char hostname[1024] = {0};
					if (gethostname(hostname, sizeof(hostname)) != 0) {
						snprintf(hostname, sizeof(hostname), "unknown");
					}

					// 取客户端IP,Port
					char client_ip[20] = {0};
					char client_port[20] = {0};
					struct sockaddr_in sa;
					int len = sizeof(sa);
					if (!getpeername(connfd, (struct sockaddr *)&sa, &len)) {
						snprintf(client_ip, sizeof(client_ip), "%s", inet_ntoa(sa.sin_addr));
						snprintf(client_port, sizeof(client_port), "%d", ntohs(sa.sin_port));
					}

					
					// 取一个新的client
					int i = new_idx_from_child_st();
					if (i == -1) {
						log_error("new_idx_from_client_st fail: maybe client queue is full.");

						// send error
						snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END);
						write(connfd, greetting, strlen(greetting));
						log_debug("send fd[%d]:%s", connfd, greetting);

						continue;		
					}
					child_st[i].used = 1;
					
					int pir[2];
					int piw[2];
					if (pipe(pir) == -1) {
						log_error("unable to create pipe:%s", strerror(errno));
					
						// send error
						snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END);
						write(connfd, greetting, strlen(greetting));
						log_debug("send fd[%d]:%s", connfd, greetting);
						
						continue;
					}
					if (pipe(piw) == -1) {
						log_error("unable to create pipe:%s", strerror(errno));

						close(pir[0]);
						close(pir[1]);
						pir[0] = -1;
						pir[1] = -1;

						// send error
                        snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END);
                        write(connfd, greetting, strlen(greetting));
                        log_debug("send fd[%d]:%s", connfd, greetting);

                        continue;
					}
					log_debug("create pir[0]:%d pir[1]:%d", pir[0], pir[1]);
					log_debug("create piw[0]:%d piw[1]:%d", piw[0], piw[1]);
					
					
					// 当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程
					//fcntl(pir[0], F_SETFD, FD_CLOEXEC);			
					//fcntl(piw[1], F_SETFD, FD_CLOEXEC);			

					int f = fork();
					if (f < 0) {
						log_error("fork fail:%s", strerror(errno));

						close(pir[0]);
						close(pir[1]);
						pir[0] = -1;
						pir[1] = -1;

						close(piw[0]);
						close(piw[1]);
						piw[0] = -1;
						piw[1] = -1;
						
						child_st[i].used = 0;

						// send error
                        snprintf(greetting, sizeof(greetting), "%s ERR %s%s", TAG_GREET, hostname, DATA_END);
                        write(connfd, greetting, strlen(greetting));
                        log_debug("send fd[%d]:%s", connfd, greetting);

                        continue;
					}

					struct timeval tm;
					gettimeofday(&tm, NULL);
					snprintf(child_st[i].mid, sizeof(child_st[i].mid), "%05u%u", (uint32_t)tm.tv_usec, (uint32_t)f);
					snprintf(msg_id, sizeof(msg_id), "%s", child_st[i].mid);

					if (f == 0) {
						// 子进程
						close(pir[0]);
						close(piw[1]);
						close(listenfd);

						char _cmid[512] = {0};
						char _cchild_st[512] = {0};
						char _ccip[20] = {0};
						char _ccport[20] = {0};

						snprintf(_cmid, sizeof(_cmid), "-m%s", child_st[i].mid);
						snprintf(_cchild_st, sizeof(_cchild_st), "-c%s", config_st.child_cf);
						snprintf(_ccip, sizeof(_ccip), "-i%s", client_ip);
						snprintf(_ccport, sizeof(_ccport), "-p%s", client_port);

						char *args[6];
						args[0] = "./liao_command";
						args[1] = _cmid;
						args[2] = _cchild_st;
						args[3] = _ccip;
						args[4] = _ccport;
						args[5] = 0;

						if (fd_move(0, connfd) == -1) {
							log_info("%s fd_move(0, %d) failed:%d %s", child_st[i].mid, connfd, errno, strerror(errno));
							_exit(111);
						}

						if (fd_move(1, pir[1]) == -1) {
							log_info("%s fd_move(pipe_w, %d) failed:%d %s", child_st[i].mid, pir[1], errno, strerror(errno));
							_exit(111);
						}
						if (fd_move(2, piw[0]) == -1) {
							log_info("%s fd_move(pipe_r, %d) failed:%d %s", child_st[i].mid, piw[0], errno, strerror(errno));
							_exit(111);
						}

						if (execvp(*args, args) == -1) {
							log_error("execp fail:%s", strerror(errno));
							_exit(111);
						}
						//if (error_temp(errno))
						//	_exit(111);
						log_debug("execp succ");
						_exit(100);							

					}

					close(connfd);
			
					child_st[i].pipe_r_in = pir[0];
					close(pir[1]);
					pir[1] = -1;
					child_st[i].pipe_r_out = -1;

					child_st[i].pipe_w_out = piw[1];
					close(piw[0]);
					piw[0] = -1;
					child_st[i].pipe_w_in = -1;


					child_st[i].pid = f;

					
					if (setnonblocking(child_st[i].pipe_r_in) != 0) {
						log_error("setnonblocking fd[%d] failed", child_st[i].pipe_r_in);
					}

					
					struct epoll_event pipe_in_ev;
					pipe_in_ev.events = EPOLLIN | EPOLLET;	
					pipe_in_ev.data.fd = child_st[i].pipe_r_in;
					if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_in_ev.data.fd, &pipe_in_ev) == -1) {
						log_error("epoll_ctl client fd[%d] EPOLL_CTL_ADD failed:[%d]%s", pipe_in_ev.data.fd, errno, strerror(errno));
					}
					log_debug("epoll_add fd[%d]", pipe_in_ev.data.fd);

					

				} else if (connfd == -1) {
					if (errno != EAGAIN && errno != ECONNABORTED && errno != EPROTO && errno != EINTR) {
						log_error("accept failed:[%d]%s", errno, strerror(errno));
					}

					continue;
				}

			} else if (epoll_evts[epoll_i].events & EPOLLIN) {
				
				int ci = get_idx_with_sockfd(evt_fd);
				if (ci < 0) {
					log_error("socket fd[%d] get_idx_with_sockfd fail", evt_fd);
					continue;
				}	
				log_debug("%s get event EPOLLIN: epoll_i[%d] fd[%d] get d_i[%d] fd[%d], used[%d]", child_st[ci].mid, epoll_i, epoll_evts[epoll_i].data.fd, child_st[ci].pipe_r_in, child_st[ci].used);

				// 读取内容 ----------------------
				char inbuf[BUF_SIZE] = {0};
				char *pinbuf = inbuf;
				int inbuf_size = BUF_SIZE;
				int inbuf_len = 0;
				char ch;
				
				
				do {
					i = 0;
					nread = read(child_st[ci].pipe_r_in, inbuf, inbuf_size);
					log_debug("%s read from liao_command:[%d]", child_st[ci].mid, nread);

					if (nread == -1) {
						// read error on a readable pipe? be serious
						//log_error("it is failed from fd[%d] read. error:%d %s", child_st[ci].fd_in, errno, strerror(errno));
						//log_debug("it is failed from fd[%d] read. error:%d %s", child_st[ci].pipe_r_in, errno, strerror(errno));
						break;

					} else if (nread > 0) {
						if (child_st[ci].mfp_out == NULL) {
							child_st[ci].mfp_out = mopen(MAX_BLOCK_SIZE, NULL, NULL);
							if (child_st[ci].mfp_out == NULL) {
								log_debug("%s mopen for body fail", child_st[ci].mid);
								break;
							}
						}	

						while (i < nread) {	
							ch = inbuf[i];	
							
							if ((inbuf_size - inbuf_len) < 2) {
								int r = fast_write(child_st[ci].mfp_out, inbuf, inbuf_len);
								if (r == 0) {
									log_error("%s fast_write fail", child_st[ci].mid);
									break;
								}	

								memset(inbuf, 0, inbuf_size);
								inbuf_len = 0;
							}	

							mybyte_copy(pinbuf + inbuf_len, 1, &ch);
							inbuf_len++;	

							if (ch == '\n') {
								if (inbuf_len > 0) {
									int r = fast_write(child_st[ci].mfp_out, inbuf, inbuf_len);
									if (r == 0) {
										log_error("%s fast_write fail", child_st[ci].mid);
										break;
									}

									memset(inbuf, 0, inbuf_size);
									inbuf_len = 0;
								}
								
								// 处理当前指令
								// ...
								process_system(&child_st[ci]);
								// ...
								
								// 处理完成后
								if (child_st[ci].mfp_out != NULL) {
									mclose(child_st[ci].mfp_out);
									child_st[ci].mfp_out = NULL;
									
									child_st[ci].mfp_out = mopen(MAX_BLOCK_SIZE, NULL, NULL);
									if (child_st[ci].mfp_out == NULL) {
										log_error("mopen fail for mfp_out");
										break;
									}
								}
								
								pinbuf = inbuf + 0;
							}

							i++;
						}
						
						
					} else {
						break;
					}

				} while (1);	


			} else if ((epoll_evts[epoll_i].events & EPOLLHUP) && (epoll_evts[epoll_i].data.fd != listenfd)) {

				int ci = get_idx_with_sockfd(evt_fd);
				if ( ci < 0 ) {
					log_error("get_idx_with_sockfd(%d) fail, so not write", evt_fd);

					continue;
				}
				log_debug("%s get event EPOLLHUP: epoll_i[%d] fd[%d] get d_i[%d] fd[%d], used[%d]", child_st[ci].mid, epoll_i, epoll_evts[epoll_i].data.fd, child_st[ci].pipe_r_in, child_st[ci].used);

				epoll_delete_evt(epoll_fd, child_st[ci].pipe_r_in);

				continue;

			}


		}
		sig_childunblock();

	}

	close(epoll_fd);
	close(listenfd);

	log_info("i'm finish");
    
	return 0;
}