/** * Opens the socket server for communication. * @param transport Transport handle * @param host Hostname or IP address (using local address if NULL) * @param port Port number for listen port * @return Returns LWPB_ERR_OK if successful. */ lwpb_err_t lwpb_transport_socket_server_open(lwpb_transport_t transport, const char *host, u16_t port) { struct lwpb_transport_socket_server *socket_server = (struct lwpb_transport_socket_server *) transport; lwpb_err_t ret = LWPB_ERR_OK; int status; struct addrinfo hints; struct addrinfo *res; struct sockaddr_in *addr; char tmp[16]; int yes = 1; if (socket_server->socket != -1) { LWPB_INFO("Socket server already opened"); return LWPB_ERR_OK; } // Resolve hostname LWPB_DEBUG("Resolving hostname '%s'", host); memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; // IPv4 hints.ai_socktype = SOCK_STREAM; // TCP stream sockets hints.ai_flags = AI_PASSIVE; // Fill in the IP snprintf(tmp, sizeof(tmp), "%d", port); if ((status = getaddrinfo(host, tmp, &hints, &res)) != 0) { LWPB_ERR("getaddrinfo error: %s\n", gai_strerror(status)); ret = LWPB_ERR_NET_INIT; goto out; } addr = (struct sockaddr_in *) res->ai_addr; inet_ntop(res->ai_family, &addr->sin_addr, tmp, sizeof(tmp)); // Create server socket LWPB_DEBUG("Creating server socket"); socket_server->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (socket_server->socket == -1) { LWPB_ERR("Cannot create server socket"); ret = LWPB_ERR_NET_INIT; goto out; } // Reuse address if necessary if (setsockopt(socket_server->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { LWPB_ERR("Cannot set SO_REUSEADDR (error: %d)", errno); ret = LWPB_ERR_NET_INIT; goto out; } // Make non-blocking make_nonblock(socket_server->socket); // Bind listen socket LWPB_DEBUG("Binding server socket to %s:%d", tmp, port); if (bind(socket_server->socket, res->ai_addr, res->ai_addrlen) == -1) { LWPB_ERR("Cannot bind server socket (errno: %d)", errno); ret = LWPB_ERR_NET_INIT; goto out; } // Start listening LWPB_DEBUG("Start listening on server socket"); if (listen(socket_server->socket, LWPB_TRANSPORT_SOCKET_SERVER_CONNS) == -1) { LWPB_ERR("Cannot listen on server socket (errno: %d)", errno); close(socket_server->socket); ret = LWPB_ERR_NET_INIT; goto out; } out: freeaddrinfo(res); return ret; }
/** * Opens the socket client for communication. * @param transport Transport handle * @param host Hostname or IP address (using local address if NULL) * @param port Port number for listen port * @return Returns LWPB_ERR_OK if successful. */ lwpb_err_t lwpb_transport_socket_client_open(lwpb_transport_t transport, const char *host, u16_t port) { struct lwpb_transport_socket_client *socket_client = (struct lwpb_transport_socket_client *) transport; lwpb_err_t ret = LWPB_ERR_OK; int status; struct addrinfo hints; struct addrinfo *res; struct sockaddr_in *addr; char tmp[16]; int yes = 1; if (socket_client->socket != -1) { LWPB_INFO("Socket client already opened"); return LWPB_ERR_OK; } // Allocate receive buffer ret = lwpb_transport_alloc_buf(&socket_client->super, &socket_client->buf, &socket_client->len); if (ret != LWPB_ERR_OK) return ret; socket_client->pos = socket_client->buf; // Resolve hostname LWPB_DEBUG("Resolving hostname '%s'", host); memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; // IPv4 hints.ai_socktype = SOCK_STREAM; // TCP stream sockets hints.ai_flags = AI_PASSIVE; // Fill in the IP snprintf(tmp, sizeof(tmp), "%d", port); if ((status = getaddrinfo(host, tmp, &hints, &res)) != 0) { LWPB_ERR("getaddrinfo error: %s\n", gai_strerror(status)); ret = LWPB_ERR_NET_INIT; goto out; } addr = (struct sockaddr_in *) res->ai_addr; inet_ntop(res->ai_family, &addr->sin_addr, tmp, sizeof(tmp)); // Create client socket LWPB_DEBUG("Creating client socket"); socket_client->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (socket_client->socket == -1) { LWPB_ERR("Cannot create client socket"); ret = LWPB_ERR_NET_INIT; goto out; } // Reuse address if necessary if (setsockopt(socket_client->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { LWPB_ERR("Cannot set SO_REUSEADDR (error: %d)", errno); ret = LWPB_ERR_NET_INIT; goto out; } // Connect to server LWPB_DEBUG("Connecting to %s:%d", tmp, port); if (connect(socket_client->socket, res->ai_addr, res->ai_addrlen) == -1) { LWPB_ERR("Cannot open connection (errno: %d)", errno); ret = LWPB_ERR_NET_INIT; goto out; } // Make non-blocking make_nonblock(socket_client->socket); out: freeaddrinfo(res); return ret; }