int flom_handle_set_unicast_address(flom_handle_t *handle, const char *value) { FLOM_TRACE(("flom_handle_set_unicast_address: " "old value='%s', new value='%s'\n", STRORNULL(flom_config_get_unicast_address(handle->config)), STRORNULL(value))); switch (handle->state) { case FLOM_HANDLE_STATE_INIT: case FLOM_HANDLE_STATE_DISCONNECTED: flom_config_set_unicast_address(handle->config, (const gchar *)value); /* reset socket name and multicast address*/ if (NULL != value) { flom_handle_set_socket_name(handle, NULL); flom_handle_set_multicast_address(handle, NULL); } /* if (NULL != value) */ break; default: FLOM_TRACE(("flom_handle_set_unicast_address: state %d " \ "is not compatible with set operation\n", handle->state)); return FLOM_RC_API_IMMUTABLE_HANDLE; } /* switch (handle->state) */ return FLOM_RC_OK; }
void flom_handle_set_unicast_address(flom_handle_t *handle, const char *value) { FLOM_TRACE(("flom_handle_set_unicast_address: " "old value='%s', new value='%s'\n", STRORNULL(flom_config_get_unicast_address(handle->config)), STRORNULL(value))); flom_config_set_unicast_address(handle->config, (const gchar *)value); /* reset socket name and multicast address*/ if (NULL != value) { flom_handle_set_socket_name(handle, NULL); flom_handle_set_multicast_address(handle, NULL); } /* if (NULL != value) */ }
int flom_tcp_listen(flom_tcp_t *obj) { enum Exception { GETADDRINFO_ERROR , BIND_ERROR , LISTEN_ERROR , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; struct addrinfo *result = NULL; int fd = FLOM_NULL_FD; FLOM_TRACE(("flom_tcp_listen\n")); TRY { struct addrinfo hints, *gai = NULL; int errcode; char port[100]; struct sockaddr_in6 sa6; struct sockaddr *sa = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = obj->domain; hints.ai_socktype = obj->socket_type; hints.ai_protocol = IPPROTO_TCP; snprintf(port, sizeof(port), "%u", flom_config_get_unicast_port(obj->config)); FLOM_TRACE(("flom_tcp_listen: binding address '%s' " "and port %s\n", flom_config_get_unicast_address( obj->config), port)); if (0 != (errcode = getaddrinfo( flom_config_get_unicast_address(obj->config), port, &hints, &result))) { FLOM_TRACE(("flom_tcp_listen/getaddrinfo(): " "errcode=%d '%s'\n", errcode, gai_strerror(errcode))); THROW(GETADDRINFO_ERROR); } else { int bound = FALSE; int sock_opt = 1; FLOM_TRACE_ADDRINFO("flom_tcp_listen/getaddrinfo(): ", result); /* traverse the list and try to bind... */ gai = result; while (NULL != gai && !bound) { sa = gai->ai_addr; /* IPv6 addresses could need sin6_scope_id set if the user specified a network interface */ if (AF_INET6 == gai->ai_family && NULL != flom_config_get_network_interface(obj->config)) { memcpy(&sa6, sa, gai->ai_addrlen); sa6.sin6_scope_id = flom_config_get_sin6_scope_id( obj->config); sa = (struct sockaddr *)&sa6; FLOM_TRACE(("flom_tcp_listen: overriding field " "sin6_scope_id with value %u\n", sa6.sin6_scope_id)); } FLOM_TRACE_SOCKADDR("flom_tcp_listen: ai_addr ", (void *)sa, gai->ai_addrlen); if (-1 == (fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol))) { FLOM_TRACE(("flom_tcp_listen/socket(): " "errno=%d '%s', skipping...\n", errno, strerror(errno))); gai = gai->ai_next; } else if (-1 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt, sizeof(sock_opt))) { FLOM_TRACE(("flom_tcp_listen/setsockopt() : " "errno=%d '%s', skipping...\n", errno, strerror(errno))); gai = gai->ai_next; close(fd); fd = FLOM_NULL_FD; } else if (-1 == bind(fd, sa, gai->ai_addrlen)) { FLOM_TRACE(("flom_tcp_listen/bind() : " "errno=%d '%s', skipping...\n", errno, strerror(errno))); gai = gai->ai_next; close(fd); fd = FLOM_NULL_FD; } else { bound = TRUE; FLOM_TRACE(("flom_tcp_listen: bound!\n")); } } /* while (NULL != gai && !bound) */ if (!bound) THROW(BIND_ERROR); } if (-1 == listen(fd, LISTEN_BACKLOG)) THROW(LISTEN_ERROR); /* set output values */ obj->sockfd = fd; obj->addrlen = gai->ai_addrlen; memcpy(&obj->sa_storage, sa, obj->addrlen); fd = FLOM_NULL_FD; /* avoid socket close by clean-up section */ THROW(NONE); } CATCH { switch (excp) { case GETADDRINFO_ERROR: ret_cod = FLOM_RC_GETADDRINFO_ERROR; break; case BIND_ERROR: ret_cod = FLOM_RC_BIND_ERROR; break; case LISTEN_ERROR: ret_cod = FLOM_RC_LISTEN_ERROR; break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ if (NULL != result) freeaddrinfo(result); if (FLOM_NULL_FD != fd) close(fd); FLOM_TRACE(("flom_tcp_listen/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
int flom_tcp_connect(flom_tcp_t *obj) { enum Exception { GETADDRINFO_ERROR , CONNECTION_REFUSED , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; struct addrinfo *result = NULL; int fd = FLOM_NULL_FD; FLOM_TRACE(("flom_tcp_connect\n")); TRY { struct addrinfo hints; const struct addrinfo *p = NULL; char port_string[100]; int errcode; FLOM_TRACE(("flom_tcp_connect: connecting to address '%s' " "and port %d\n", flom_config_get_unicast_address(obj->config), flom_config_get_unicast_port(obj->config))); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; /* interface name is specified, IPv6 is forced */ if (NULL != flom_config_get_network_interface(obj->config)) hints.ai_family = AF_INET6; else hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; snprintf(port_string, sizeof(port_string), "%u", flom_config_get_unicast_port(obj->config)); if (0 != (errcode = getaddrinfo( flom_config_get_unicast_address(obj->config), port_string, &hints, &result))) { FLOM_TRACE(("flom_tcp_connect/getaddrinfo(): " "errcode=%d '%s'\n", errcode, gai_strerror(errcode))); THROW(GETADDRINFO_ERROR); } FLOM_TRACE_ADDRINFO("flom_tcp_connect/getaddrinfo(): ", result); if (NULL == (p = flom_tcp_try_connect(obj->config, result, &fd))) { /* domain must be set even if the connection failed because it's necessary to start a new daemon */ obj->domain = result->ai_family; THROW(CONNECTION_REFUSED); } obj->domain = result->ai_family; obj->sockfd = fd; obj->socket_type = hints.ai_socktype; obj->addrlen = p->ai_addrlen; memcpy(&obj->sa_storage, p->ai_addr, obj->addrlen); FLOM_TRACE(("flom_tcp_connect: domain=%d, sockfd=%d, socket_type=%d, " "addrlen=%u\n", obj->domain, obj->sockfd, obj->addrlen)); FLOM_TRACE_SOCKADDR("flom_tcp_connect: ", &obj->sa, obj->addrlen); THROW(NONE); } CATCH { switch (excp) { case GETADDRINFO_ERROR: ret_cod = FLOM_RC_GETADDRINFO_ERROR; break; case CONNECTION_REFUSED: ret_cod = FLOM_RC_CONNECTION_REFUSED; break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ if (NULL != result) freeaddrinfo(result); /* in case of error, close the socket */ if (FLOM_RC_OK != ret_cod && FLOM_NULL_FD != fd) close(fd); FLOM_TRACE(("flom_tcp_connect/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
const char *flom_handle_get_unicast_address(const flom_handle_t *handle) { FLOM_TRACE(("flom_handle_get_unicast_address: value='%s'\n", STRORNULL(flom_config_get_unicast_address(handle->config)))); return (const char *)flom_config_get_unicast_address(handle->config); }