void flom_handle_delete(flom_handle_t *handle) { /* dummy loop */ while (TRUE) { int ret_cod; /* check flom library is initialized */ if (FLOM_RC_OK != flom_init_check()) break; FLOM_TRACE(("flom_handle_delete: handle=%p\n", handle)); /* check handle is not NULL */ if (NULL == handle) { FLOM_TRACE(("flom_handle_delete: handle is null, skipping...\n")); break; } /* clean object handle */ if (FLOM_RC_OK != (ret_cod = flom_handle_clean(handle))) { FLOM_TRACE(("flom_handle_new: flom_handle_clean returned %d, " "ignoring it and going on...\n", ret_cod)); } /* reset the object handle to prevent misuse of the associated memory */ memset(handle, 0, sizeof(flom_handle_t)); /* remove object handle */ g_free(handle); FLOM_TRACE(("flom_handle_new: deallocated handle %p\n", handle)); /* exit the loop after one cycle */ break; } /* while (TRUE) */ FLOM_TRACE(("flom_handle_delete: exiting\n")); }
int flom_resource_simple_can_lock(flom_resource_t *resource, flom_lock_mode_t lock) { static const flom_lock_mode_t lock_table[ FLOM_LOCK_MODE_N][FLOM_LOCK_MODE_N] = { { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE } , { TRUE, TRUE, TRUE, TRUE, TRUE, FALSE } , { TRUE, TRUE, TRUE, FALSE, FALSE, FALSE } , { TRUE, TRUE, FALSE, TRUE, FALSE, FALSE } , { TRUE, TRUE, FALSE, FALSE, FALSE, FALSE } , { TRUE, FALSE, FALSE, FALSE, FALSE, FALSE } }; GSList *p = NULL; flom_lock_mode_t old_lock; int can_lock = TRUE; FLOM_TRACE(("flom_resource_simple_can_lock: checking lock=%d\n", lock)); p = resource->data.simple.holders; while (NULL != p) { old_lock = ((struct flom_rsrc_conn_lock_s *)p->data)->info.lock_mode; FLOM_TRACE(("flom_resource_simple_can_lock: current_lock=%d, " "asked_lock=%d, lock_table[%d][%d]=%d\n", old_lock, lock, old_lock, lock, lock_table[old_lock][lock])); can_lock &= lock_table[old_lock][lock]; if (!can_lock) break; else p = p->next; } /* while (NULL != p) */ return can_lock; }
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; }
int flom_tcp_close(flom_tcp_t *obj) { enum Exception { CLOSE_ERROR , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; FLOM_TRACE(("flom_tcp_close\n")); TRY { if (FLOM_NULL_FD == obj->sockfd) { FLOM_TRACE(("flom_tcp_close: sockfd is NULL, skipping...\n")); } else { if (0 != close(obj->sockfd)) THROW(CLOSE_ERROR); obj->sockfd = FLOM_NULL_FD; } /* if (FLOM_NULL_FD == obj->sockfd) */ THROW(NONE); } CATCH { switch (excp) { case CLOSE_ERROR: ret_cod = FLOM_RC_CLOSE_ERROR; break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ FLOM_TRACE(("flom_tcp_close/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
void flom_resource_simple_free(flom_resource_t *resource) { /* clean-up holders list... */ FLOM_TRACE(("flom_resource_simple_free: cleaning-up holders list...\n")); while (NULL != resource->data.simple.holders) { struct flom_rsrc_conn_lock_s *cl = (struct flom_rsrc_conn_lock_s *)resource->data.simple.holders->data; resource->data.simple.holders = g_slist_remove( resource->data.simple.holders, cl); flom_rsrc_conn_lock_delete(cl); } resource->data.simple.holders = NULL; /* clean-up waitings queue... */ FLOM_TRACE(("flom_resource_simple_free: cleaning-up waitings queue...\n")); while (!g_queue_is_empty(resource->data.simple.waitings)) { struct flom_rsrc_conn_lock_s *cl = (struct flom_rsrc_conn_lock_s *)g_queue_pop_head( resource->data.simple.waitings); flom_rsrc_conn_lock_delete(cl); } g_queue_free(resource->data.simple.waitings); resource->data.simple.waitings = NULL; /* releasing resource name */ if (NULL != resource->name) g_free(resource->name); resource->name = NULL; }
int flom_conn_set_keepalive(flom_config_t *config, int fd) { enum Exception { NULL_OBJECT , SETSOCKOPT_ERROR1 , SETSOCKOPT_ERROR2 , SETSOCKOPT_ERROR3 , SETSOCKOPT_ERROR4 , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; FLOM_TRACE(("flom_conn_set_keepalive\n")); TRY { int optval; socklen_t optlen = sizeof(optval); if (FLOM_NULL_FD == fd) THROW(NULL_OBJECT); FLOM_TRACE(("flom_conn_set_keepalive: setting SO_KEEPALIVE " "for socket fd=%d\n", fd)); /* set SO_KEEPALIVE feature for this socket */ optval = 1; if (-1 == setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) THROW(SETSOCKOPT_ERROR1); /* set tcp_keepalive_time parameter related to SO_KEEPALIVE */ optval = flom_config_get_tcp_keepalive_time(config); if (-1 == setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen)) THROW(SETSOCKOPT_ERROR2); /* set tcp_keepalive_intvl parameter related to SO_KEEPALIVE */ optval = flom_config_get_tcp_keepalive_intvl(config); if (-1 == setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen)) THROW(SETSOCKOPT_ERROR3); /* set tcp_keepalive_probes parameter related to SO_KEEPALIVE */ optval = flom_config_get_tcp_keepalive_probes(config); if (-1 == setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &optval, optlen)) THROW(SETSOCKOPT_ERROR4); THROW(NONE); } CATCH { switch (excp) { case NULL_OBJECT: ret_cod = FLOM_RC_NULL_OBJECT; break; case SETSOCKOPT_ERROR1: case SETSOCKOPT_ERROR2: case SETSOCKOPT_ERROR3: case SETSOCKOPT_ERROR4: ret_cod = FLOM_RC_SETSOCKOPT_ERROR; break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ FLOM_TRACE(("flom_conn_set_keepalive/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
gchar *flom_tcp_retrieve_peer_name(const flom_tcp_t *obj) { struct sockaddr_storage sa; socklen_t addrlen = sizeof(sa); char host[NI_MAXHOST+1]; char serv[NI_MAXSERV+1]; int ret_cod; char *tmp; size_t tmp_size; memset(&sa, 0, sizeof(sa)); if (0 != getpeername(obj->sockfd, (struct sockaddr *)&sa, &addrlen)) { FLOM_TRACE(("flom_tcp_retrieve_peer_name/getpeername: errno=%d\n", errno)); return NULL; } if (0 != (ret_cod = getnameinfo( (struct sockaddr *)&sa, addrlen, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV))) { FLOM_TRACE(("flom_tcp_retrieve_peer_name/getnameinfo: ret_cod=%d, " "errno=%d\n", ret_cod, errno)); return NULL; } tmp_size = strlen(host) + strlen(serv) + 2; if (NULL != (tmp = g_try_malloc0(tmp_size))) { snprintf(tmp, tmp_size, "%s/%s", host, serv); } return tmp; }
int flom_handle_clean(flom_handle_t *handle) { enum Exception { FLOM_HANDLE_UNLOCK_ERROR , API_INVALID_SEQUENCE , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; /* check flom library is initialized */ if (FLOM_RC_OK != (ret_cod = flom_init_check())) return ret_cod; FLOM_TRACE(("flom_handle_clean\n")); TRY { /* is the handle locked? we must unlock it before going on... */ if (FLOM_HANDLE_STATE_LOCKED == handle->state) { if (FLOM_RC_OK != (ret_cod = flom_handle_unlock(handle))) THROW(FLOM_HANDLE_UNLOCK_ERROR); } /* check handle state */ if (FLOM_HANDLE_STATE_INIT != handle->state && FLOM_HANDLE_STATE_DISCONNECTED != handle->state) { FLOM_TRACE(("flom_handle_clean: handle->state=%d\n", handle->state)); THROW(API_INVALID_SEQUENCE); } /* release memory allocated for configuration object */ flom_config_free(handle->config); g_free(handle->config); handle->config = NULL; /* release memory of connection data structure */ g_free(handle->conn); handle->conn = NULL; /* release memory of locked element */ g_free(handle->locked_element); handle->locked_element = NULL; /* clean handle state */ handle->state = FLOM_HANDLE_STATE_CLEANED; THROW(NONE); } CATCH { switch (excp) { case FLOM_HANDLE_UNLOCK_ERROR: break; case API_INVALID_SEQUENCE: ret_cod = FLOM_RC_API_INVALID_SEQUENCE; break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ FLOM_TRACE(("flom_handle_clean/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
int flom_tcp_recv(const flom_tcp_t *obj, void *buf, size_t len, size_t *received, struct sockaddr *src_addr, socklen_t *addrlen) { enum Exception { INVALID_SOCKET_TYPE , RECV_ERROR , RECVFROM_ERROR , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; FLOM_TRACE(("flom_tcp_recv\n")); TRY { switch (obj->socket_type) { case SOCK_STREAM: if (0 > (*received = recv(obj->sockfd, buf, len, 0))) THROW(RECV_ERROR); break; case SOCK_DGRAM: if (0 > (*received = recvfrom( obj->sockfd, buf, len, 0, (struct sockaddr *)src_addr, addrlen))) THROW(RECVFROM_ERROR); FLOM_TRACE_HEX_DATA("flom_tcp_recv: from ", (void *)src_addr, *addrlen); break; default: THROW(INVALID_SOCKET_TYPE); } /* switch (type) */ FLOM_TRACE(("flom_tcp_recv: fd=%d returned " SSIZE_T_FORMAT " bytes '%*.*s'\n", obj->sockfd, *received, *received, *received, buf)); THROW(NONE); } CATCH { switch (excp) { case INVALID_SOCKET_TYPE: ret_cod = FLOM_RC_INVALID_OPTION; break; case RECV_ERROR: ret_cod = FLOM_RC_RECV_ERROR; break; case RECVFROM_ERROR: ret_cod = FLOM_RC_RECVFROM_ERROR; break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ FLOM_TRACE(("flom_tcp_recv/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
void flom_conn_trace(const flom_conn_t *conn) { FLOM_TRACE(("flom_conn_trace: object=%p\n", conn)); FLOM_TRACE(("flom_conn_trace: " "fd=%d, type=%d, state=%d, wait=%d, msg=%p, parser=%p, " "addr_len=%d\n", flom_tcp_get_sockfd(&conn->tcp), flom_tcp_get_socket_type(&conn->tcp), conn->state, conn->wait, conn->msg, conn->parser, flom_tcp_get_addrlen(&conn->tcp))); }
int flom_conn_send(flom_conn_t *obj, const void *buf, size_t len) { int ret_cod = FLOM_RC_OK; FLOM_TRACE(("flom_conn_send\n")); if (NULL != obj->tls) ret_cod = flom_tls_send(obj->tls, buf, len); else ret_cod = flom_tcp_send(&obj->tcp, buf, len); FLOM_TRACE(("flom_conn_send/" "ret_cod=%d/errno=%d\n", ret_cod, errno)); return ret_cod; }
void flom_handle_set_resource_timeout(flom_handle_t *handle, int value) { FLOM_TRACE(("flom_handle_set_resource_timeout: " "old value=%d, new value=%d\n", flom_config_get_resource_timeout(handle->config), value)); return flom_config_set_resource_timeout(handle->config, (int)value); }
void flom_handle_set_resource_quantity(flom_handle_t *handle, int value) { FLOM_TRACE(("flom_handle_set_resource_quantity: " "old value=%d, new value=%d\n", flom_config_get_resource_quantity(handle->config), value)); flom_config_set_resource_quantity(handle->config, (int)value); }
void flom_handle_set_resource_create(flom_handle_t *handle, int value) { FLOM_TRACE(("flom_handle_set_resource_create: " "old value=%d, new value=%d\n", flom_config_get_resource_create(handle->config), value)); return flom_config_set_resource_create(handle->config, value); }
void flom_handle_set_discovery_ttl(flom_handle_t *handle, int value) { FLOM_TRACE(("flom_handle_set_discovery_ttl: " "old value=%d, new value=%d\n", flom_config_get_discovery_ttl(handle->config), value)); flom_config_set_discovery_ttl(handle->config, (gint)value); }
void flom_handle_set_unicast_port(flom_handle_t *handle, int value) { FLOM_TRACE(("flom_handle_set_unicast_port: " "old value=%d, new value=%d\n", flom_config_get_unicast_port(handle->config), value)); flom_config_set_unicast_port(handle->config, (gint)value); }
const char *flom_handle_get_tls_ca_certificate(const flom_handle_t *handle) { FLOM_TRACE(("flom_handle_get_tls_ca_certificate: value='%s'\n", STRORNULL( flom_config_get_tls_ca_certificate(handle->config)))); return (const char *)flom_config_get_tls_ca_certificate(handle->config); }
void flom_handle_set_lock_mode(flom_handle_t *handle, flom_lock_mode_t value) { FLOM_TRACE(("flom_handle_set_lock_mode: " "old value=%d, new value=%d\n", flom_config_get_lock_mode(handle->config), value)); flom_config_set_lock_mode(handle->config, value); }
void flom_tcp_init(flom_tcp_t *obj, flom_config_t *config) { FLOM_TRACE(("flom_tcp_init\n")); /* memory reset */ memset(obj, 0, sizeof(flom_tcp_t)); obj->config = config; }
const char *flom_handle_get_trace_filename(const flom_handle_t *handle) { FLOM_TRACE(("flom_handle_get_trace_filename: value='%s'\n", STRORNULL(flom_config_get_command_trace_file( handle->config)))); return (const char *)flom_config_get_command_trace_file(handle->config); }
void flom_handle_set_trace_filename(flom_handle_t *handle, const char *value) { FLOM_TRACE(("flom_handle_set_trace_filename: " "old value='%s', new value='%s'\n", STRORNULL(flom_config_get_command_trace_file(handle->config)), STRORNULL(value))); flom_config_set_command_trace_file(handle->config, (const gchar *)value); }
int flom_conn_authenticate(flom_conn_t *conn, const gchar *peer_id, int tls_check_peer_id) { enum Exception { TLS_CERT_CHECK_ERROR , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; gchar *unique_id = NULL; gchar *peer_addr = NULL; FLOM_TRACE(("flom_conn_authenticate\n")); TRY { if (NULL == flom_conn_get_tls(conn)) { FLOM_TRACE(("flom_conn_authenticate: this is not a TLS coonection " "and authentication can not be performed\n")); } else if (tls_check_peer_id) { peer_addr = flom_tcp_retrieve_peer_name( flom_conn_get_tcp(conn)); if (FLOM_RC_OK != (ret_cod = flom_tls_cert_check( flom_conn_get_tls(conn), peer_id, peer_addr))) { THROW(TLS_CERT_CHECK_ERROR); } } /* if (tls_check_peer_id) */ THROW(NONE); } CATCH { switch (excp) { case TLS_CERT_CHECK_ERROR: break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ /* unique id object clean-up */ if (NULL != unique_id) g_free(unique_id); /* peer address object clean-up */ if (NULL != peer_addr) g_free(peer_addr); FLOM_TRACE(("flom_conn_authenticate/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
void flom_handle_set_resource_idle_lifespan(flom_handle_t *handle, int value) { FLOM_TRACE(("flom_handle_set_resource_idle_lifespan: " "old value=%d, new value=%d\n", flom_config_get_resource_idle_lifespan(handle->config), value)); flom_config_set_resource_idle_lifespan(handle->config, (gint)value); }
int flom_handle_set_resource_name(flom_handle_t *handle, const char *value) { FLOM_TRACE(("flom_handle_set_resource_name: " "old value='%s', new value='%s'\n", STRORNULL(flom_config_get_resource_name(handle->config)), STRORNULL(value))); return flom_config_set_resource_name(handle->config, (const gchar *)value); }
void flom_conn_delete(flom_conn_t *obj) { FLOM_TRACE(("flom_conn_delete: obj=%p\n", obj)); if (NULL != obj) { FLOM_TRACE(("flom_conn_delete: obj->msg=%p\n", obj->msg)); /* remove msg struct */ if (NULL != obj->msg) { flom_msg_free(obj->msg); g_free(obj->msg); obj->msg = NULL; } /* clean TLS object */ flom_tls_delete(obj->tls); obj->tls = NULL; /* remove object itself */ g_free(obj); } }
int flom_handle_set_unicast_port(flom_handle_t *handle, int value) { FLOM_TRACE(("flom_handle_set_unicast_port: " "old value=%d, new value=%d\n", flom_config_get_unicast_port(handle->config), value)); switch (handle->state) { case FLOM_HANDLE_STATE_INIT: case FLOM_HANDLE_STATE_DISCONNECTED: flom_config_set_unicast_port(handle->config, (gint)value); break; default: FLOM_TRACE(("flom_handle_set_unicast_port: state %d " \ "is not compatible with set operation\n", handle->state)); return FLOM_RC_API_IMMUTABLE_HANDLE; } /* switch (handle->state) */ return FLOM_RC_OK; }
const struct addrinfo *flom_tcp_try_connect( flom_config_t *config, const struct addrinfo *gai, int *fd) { const struct addrinfo *found = NULL; *fd = FLOM_NULL_FD; /* traverse the list and try to connect... */ while (NULL != gai && NULL == found) { struct sockaddr_in6 sa6; struct sockaddr *sa = gai->ai_addr; /* IPv6 addresses could need sin6_scope_id set if the user specified a network interface */ FLOM_TRACE_SOCKADDR("flom_tcp_try_connect: sa ", sa, gai->ai_addrlen); if (AF_INET6 == sa->sa_family && NULL != flom_config_get_network_interface(config)) { memcpy(&sa6, sa, gai->ai_addrlen); sa6.sin6_scope_id = flom_config_get_sin6_scope_id(config); sa = (struct sockaddr *)&sa6; FLOM_TRACE(("flom_tcp_try_connect: overriding field " "sin6_scope_id with value %u\n", sa6.sin6_scope_id)); } if (FLOM_NULL_FD == (*fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol))) { FLOM_TRACE(("flom_tcp_try_connect/socket(): " "errno=%d '%s', skipping...\n", errno, strerror(errno))); gai = gai->ai_next; } else { FLOM_TRACE_SOCKADDR("flom_tcp_try_connect: sa ", sa, gai->ai_addrlen); if (-1 == connect(*fd, sa, gai->ai_addrlen)) { FLOM_TRACE(("flom_tcp_try_connect/connect(): " "errno=%d '%s', skipping...\n", errno, strerror(errno))); gai = gai->ai_next; close(*fd); *fd = FLOM_NULL_FD; } else found = gai; } /* if (-1 == (*fd = socket( */ } /* while (NULL != gai && !connected) */ return found; }
int flom_handle_set_trace_filename(flom_handle_t *handle, const char *value) { FLOM_TRACE(("flom_handle_set_trace_filename: " "old value='%s', new value='%s'\n", STRORNULL(flom_config_get_command_trace_file(handle->config)), STRORNULL(value))); flom_config_set_command_trace_file(handle->config, (const gchar *)value); FLOM_TRACE_REOPEN(flom_config_get_command_trace_file(handle->config), FALSE); return FLOM_RC_OK; }
int flom_conn_terminate(flom_conn_t *obj) { enum Exception { TCP_CLOSE , NONE } excp; int ret_cod = FLOM_RC_INTERNAL_ERROR; FLOM_TRACE(("flom_conn_terminate\n")); TRY { if (FLOM_CONN_STATE_REMOVE != flom_conn_get_state(obj)) { flom_conn_set_state(obj, FLOM_CONN_STATE_REMOVE); if (FLOM_NULL_FD == flom_tcp_get_sockfd(&obj->tcp)) { FLOM_TRACE(("flom_conn_terminate: connection %p already " "closed, skipping...\n", obj)); } else { FLOM_TRACE(("flom_conn_terminate: closing fd=%d\n", flom_tcp_get_sockfd(&obj->tcp))); if (FLOM_RC_OK != (ret_cod = flom_tcp_close(&obj->tcp))) THROW(TCP_CLOSE); } } else { FLOM_TRACE(("flom_conn_terminate: connection %p already " "in state %d, skipping...\n", obj, flom_conn_get_state(obj))); } /* if (FLOM_CONN_STATE_REMOVE == flom_conn_get_state(c)) */ THROW(NONE); } CATCH { switch (excp) { case TCP_CLOSE: break; case NONE: ret_cod = FLOM_RC_OK; break; default: ret_cod = FLOM_RC_INTERNAL_ERROR; } /* switch (excp) */ } /* TRY-CATCH */ FLOM_TRACE(("flom_conn_terminate/excp=%d/" "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); return ret_cod; }
int flom_handle_set_resource_name(flom_handle_t *handle, const char *value) { FLOM_TRACE(("flom_handle_set_resource_name: " "old value='%s', new value='%s'\n", STRORNULL(flom_config_get_resource_name(handle->config)), STRORNULL(value))); switch (handle->state) { case FLOM_HANDLE_STATE_INIT: case FLOM_HANDLE_STATE_DISCONNECTED: case FLOM_HANDLE_STATE_CONNECTED: flom_config_set_resource_name(handle->config, (const gchar *)value); break; default: FLOM_TRACE(("flom_handle_set_resource_name: state %d " \ "is not compatible with set operation\n", handle->state)); return FLOM_RC_API_IMMUTABLE_HANDLE; } /* switch (handle->state) */ return FLOM_RC_OK; }