87 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * Copyright (c) 2021 OceanBase
 | |
|  * OceanBase CE is licensed under Mulan PubL v2.
 | |
|  * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | |
|  * You may obtain a copy of Mulan PubL v2 at:
 | |
|  *          http://license.coscl.org.cn/MulanPubL-2.0
 | |
|  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | |
|  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | |
|  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | |
|  * See the Mulan PubL v2 for more details.
 | |
|  */
 | |
| 
 | |
| static int pipefd_handle_event(pipefd_t *s)
 | |
| {
 | |
|   int ret = 0;
 | |
|   // because edge trigger, a loop is needed.
 | |
|   // Note, if an error occurs while processing a client_fd_info,
 | |
|   // the returned result will still be 0.
 | |
|   while (1) {
 | |
|     client_fd_info_t client_fd_info;
 | |
|     int rbytes = read(s->fd, &client_fd_info, sizeof(client_fd_info));
 | |
|     if (0 == rbytes) {
 | |
|       ret = EAGAIN;
 | |
|       ussl_log_error("read EOF, pipe fd may be closed, pipefd:%d, errno:%d",
 | |
|                      s->fd, errno);
 | |
|       break;
 | |
|     } else if (-1 == rbytes) {
 | |
|       if (EAGAIN != errno && EWOULDBLOCK != errno) {
 | |
|         ussl_log_error("call read failed, pipefd:%d, errno:%d", s->fd, errno);
 | |
|       }
 | |
|       ret = EAGAIN;
 | |
|       break;
 | |
|     } else {
 | |
|       clientfd_sk_t *clientfd_sk = (clientfd_sk_t *)s->fty->create((ussl_sf_t *)s->fty);
 | |
|       if (!clientfd_sk) {
 | |
|         ussl_log_error("create clientfd sock failed, the clientfd will be closed. clientfd:%d, "
 | |
|                        "gid:%lu, errno:%d",
 | |
|                        client_fd_info.client_fd, client_fd_info.client_gid, errno);
 | |
|         if (client_fd_info.client_fd >= 0) {
 | |
|           shutdown(client_fd_info.client_fd, SHUT_WR);
 | |
|           if (0 != libc_epoll_ctl(client_fd_info.org_epfd, EPOLL_CTL_ADD,
 | |
|                                   client_fd_info.client_fd, &client_fd_info.event)) {
 | |
|             ussl_log_error("give back fd to origin epoll failed, fd:%d, errno:%d",
 | |
|                            client_fd_info.client_fd, errno);
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         memcpy(&clientfd_sk->fd_info, &client_fd_info, sizeof(client_fd_info));
 | |
|         clientfd_sk->fd = client_fd_info.client_fd;
 | |
|         clientfd_sk->ep = s->ep;
 | |
|         if (0 != ussl_eloop_regist(clientfd_sk->ep, (ussl_sock_t *)clientfd_sk, EPOLLOUT)) {
 | |
|           ussl_log_warn("[pipefd_handle_event] call eloop_regist failed, the clientfd will be "
 | |
|                          "closed. clientfd:%d, gid:0x%lx, errno:%d",
 | |
|                          client_fd_info.client_fd, client_fd_info.client_gid, errno);
 | |
|           if (client_fd_info.client_fd >= 0) {
 | |
|             shutdown(client_fd_info.client_fd, SHUT_WR);
 | |
|             if (0 != libc_epoll_ctl(client_fd_info.org_epfd, EPOLL_CTL_ADD,
 | |
|                                     client_fd_info.client_fd, &client_fd_info.event)) {
 | |
|               ussl_log_warn("give back fd to origin epoll failed, fd:%d, errno:%d",
 | |
|                              client_fd_info.client_fd, errno);
 | |
|             }
 | |
|           }
 | |
|           s->fty->destroy(s->fty, (ussl_sock_t *)clientfd_sk);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int pipefd_init(ussl_eloop_t *ep, pipefd_t *s, ussl_sf_t *sf, int fd)
 | |
| {
 | |
|   int ret = 0;
 | |
|   ussl_sk_init((ussl_sock_t *)s, sf, (void *)pipefd_handle_event, fd);
 | |
|   s->ep = ep;
 | |
|   if (s->fd < 0) {
 | |
|     ret = -EIO;
 | |
|     errno = EINVAL;
 | |
|     ussl_log_error("pipefd is initialized with an invalid fd, errno:%d", errno);
 | |
|   } else if (0 != (ret = ussl_eloop_regist(ep, (ussl_sock_t *)s, EPOLLIN))) {
 | |
|     ussl_log_error("regist pipefd failed, ret:%d", ret);
 | |
|     if (s->fd >= 0) {
 | |
|       close(s->fd);
 | |
|     }
 | |
|   }
 | |
|   return ret;
 | |
| } | 
