int flb_net_server(char *port, char *listen_addr) { int socket_fd = -1; int ret; struct addrinfo hints; struct addrinfo *res, *rp; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(listen_addr, port, &hints, &res); if (ret != 0) { flb_message(FLB_MSG_ERROR, "net_server: Can't get addr info"); return -1; } for (rp = res; rp != NULL; rp = rp->ai_next) { socket_fd = flb_net_socket_create(rp->ai_family, 1); if (socket_fd == -1) { flb_message(FLB_MSG_ERROR, "Error creating server socket, retrying"); continue; } flb_net_socket_tcp_nodelay(socket_fd); flb_net_socket_reset(socket_fd); ret = flb_net_bind(socket_fd, rp->ai_addr, rp->ai_addrlen, 128); if(ret == -1) { flb_message(FLB_MSG_WARN, "Cannot listen on %s port %s", listen_addr, port); close(socket_fd); continue; } break; } freeaddrinfo(res); if (rp == NULL) { return -1; } return socket_fd; }
/* Connect to a TCP socket server and returns the file descriptor */ int flb_net_tcp_connect(char *host, unsigned long port) { int socket_fd = -1; int ret; struct addrinfo hints; struct addrinfo *res, *rp; char _port[6]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(_port, sizeof(_port), "%lu", port); ret = getaddrinfo(host, _port, &hints, &res); if (ret != 0) { flb_message(FLB_MSG_ERROR, "net_tcp_connect: Can't get addr info"); return -1; } for (rp = res; rp != NULL; rp = rp->ai_next) { socket_fd = flb_net_socket_create(rp->ai_family, 0); if (socket_fd == -1) { flb_message(FLB_MSG_ERROR, "Error creating client socket, retrying"); continue; } if (connect(socket_fd, rp->ai_addr, rp->ai_addrlen) == -1) { flb_message(FLB_MSG_ERROR, "Cannot connect to %s port %s", host, _port); close(socket_fd); continue; } break; } freeaddrinfo(res); if (rp == NULL) { return -1; } return socket_fd; }
FLB_INLINE int flb_io_net_connect(struct flb_io_upstream *u, struct flb_thread *th) { int fd; int ret; int error = 0; socklen_t len = sizeof(error); if (u->fd > 0) { close(u->fd); } /* Create the socket */ fd = flb_net_socket_create(AF_INET, FLB_TRUE); if (fd == -1) { flb_error("[io] could not create socket"); return -1; } u->fd = fd; /* Make the socket non-blocking */ flb_net_socket_nonblocking(u->fd); /* Start the connection */ ret = flb_net_tcp_fd_connect(fd, u->tcp_host, u->tcp_port); if (ret == -1) { if (errno == EINPROGRESS) { flb_debug("[upstream] connection in process"); } else { } u->event.mask = MK_EVENT_EMPTY; u->event.status = MK_EVENT_NONE; u->thread = th; ret = mk_event_add(u->evl, fd, FLB_ENGINE_EV_THREAD, MK_EVENT_WRITE, &u->event); if (ret == -1) { /* * If we failed here there no much that we can do, just * let the caller we failed */ close(fd); return -1; } /* * Return the control to the parent caller, we need to wait for * the event loop to get back to us. */ flb_thread_yield(th, FLB_FALSE); /* We got a notification, remove the event registered */ ret = mk_event_del(u->evl, &u->event); assert(ret == 0); /* Check the connection status */ if (u->event.mask & MK_EVENT_WRITE) { ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len); if (ret == -1) { flb_error("[io] could not validate socket status"); return -1; } if (error != 0) { /* Connection is broken, not much to do here */ flb_debug("[io] connection failed"); return -1; } u->event.mask = MK_EVENT_EMPTY; u->event.status = MK_EVENT_NONE; } else { return -1; } } flb_debug("[io] connection OK"); return 0; }
/* * This routine perform a TCP connection and the required TLS/SSL * handshake, */ FLB_INLINE int flb_io_net_tls_connect(struct flb_io_upstream *u, struct flb_thread *th) { int fd; int ret; int error = 0; int flag; socklen_t len = sizeof(error); struct flb_tls_session *session; if (u->fd > 0) { close(u->fd); } /* Create the socket */ fd = flb_net_socket_create(AF_INET, FLB_TRUE); if (fd == -1) { flb_error("[io] could not create socket"); return -1; } u->fd = fd; /* Make the socket non-blocking */ flb_net_socket_nonblocking(u->fd); /* Start the connection */ ret = flb_net_tcp_fd_connect(fd, u->tcp_host, u->tcp_port); if (ret == -1) { if (errno == EINPROGRESS) { flb_debug("[upstream] connection in process"); } else { close(u->fd); if (u->tls_session) { tls_session_destroy(u->tls_session); u->tls_session = NULL; } return -1; } MK_EVENT_NEW(&u->event); u->thread = th; ret = mk_event_add(u->evl, fd, FLB_ENGINE_EV_THREAD, MK_EVENT_WRITE, &u->event); if (ret == -1) { /* * If we failed here there no much that we can do, just * let the caller we failed */ flb_error("[io_tls] connect failed registering event"); close(fd); return -1; } /* * Return the control to the parent caller, we need to wait for * the event loop to get back to us. */ flb_thread_yield(th, FLB_FALSE); /* Check the connection status */ if (u->event.mask & MK_EVENT_WRITE) { ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len); if (ret == -1) { flb_error("[io_tls] could not validate socket status"); goto error; } if (error != 0) { /* Connection is broken, not much to do here */ flb_error("[io_tls] connection failed"); goto error; } } else { return -1; } } /* Configure TLS and prepare handshake */ session = u->tls_session; mbedtls_ssl_set_bio(&session->ssl, u, mbedtls_net_send, mbedtls_net_recv, NULL); retry_handshake: ret = mbedtls_ssl_handshake(&session->ssl); if (ret != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { io_tls_error(ret); goto error; } if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { flag = MK_EVENT_WRITE; } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) { flag = MK_EVENT_READ; } else { } /* * FIXME: if we need multiple reads we are invoking the same * system call multiple times. */ ret = mk_event_add(u->evl, u->event.fd, FLB_ENGINE_EV_THREAD, flag, &u->event); if (ret == -1) { goto error; } flb_thread_yield(th, FLB_FALSE); goto retry_handshake; } else { flb_debug("[io_tls] Handshake OK"); } if (u->event.status == MK_EVENT_REGISTERED) { mk_event_del(u->evl, &u->event); } flb_debug("[io_tls] connection OK"); return 0; error: if (u->event.status == MK_EVENT_REGISTERED) { mk_event_del(u->evl, &u->event); } return -1; }