/** * \brief This function is main function of new thread for client * \param *arg The pointer at verse client session */ static void *vc_new_session_thread(void *arg) { struct VSession *vsession = (struct VSession*)arg; int i; /* Start "never ending" thread of connection*/ vc_main_stream_loop(vc_ctx, vsession); pthread_mutex_lock(&vc_ctx->mutex); /* Find this session in Verse client session list */ for(i=0; i<vc_ctx->max_sessions; i++) { if(vc_ctx->vsessions[i] != NULL) { if(strcmp(vc_ctx->vsessions[i]->peer_hostname, vsession->peer_hostname)==0 && strcmp(vc_ctx->vsessions[i]->service, vsession->service)==0) { vc_ctx->vsessions[i] = NULL; break; } } } /* When connection is closed, then destroy this session*/ v_destroy_session(vsession); free(vsession); pthread_mutex_unlock(&vc_ctx->mutex); return NULL; }
/** * \brief Destroy Verse server context * * \param[in] vs_ctx The Verse server context. */ static void vs_destroy_ctx(struct VS_CTX *vs_ctx) { struct VSUser *user; int i; /* Free all data shared at verse server */ vs_node_destroy_branch(vs_ctx, vs_ctx->data.root_node, 0); /* Destroy hashed array of nodes */ v_hash_array_destroy(&vs_ctx->data.nodes); /* Destroy list of connections */ for (i=0; i<vs_ctx->max_sessions; i++) { if(vs_ctx->vsessions[i] != NULL) { v_destroy_session(vs_ctx->vsessions[i]); free(vs_ctx->vsessions[i]); vs_ctx->vsessions[i] = NULL; } } free(vs_ctx->vsessions); vs_ctx->vsessions = NULL; free(vs_ctx->port_list); vs_ctx->port_list = NULL; free(vs_ctx->tcp_io_ctx.buf); vs_ctx->tcp_io_ctx.buf = NULL; free(vs_ctx->private_cert_file); vs_ctx->private_cert_file = NULL; if(vs_ctx->ca_cert_file != NULL) { free(vs_ctx->ca_cert_file); vs_ctx->ca_cert_file = NULL; } free(vs_ctx->public_cert_file); vs_ctx->public_cert_file = NULL; free(vs_ctx->hostname); vs_ctx->hostname = NULL; free(vs_ctx->ded); vs_ctx->ded = NULL; if(vs_ctx->csv_user_file != NULL) { free(vs_ctx->csv_user_file); vs_ctx->csv_user_file = NULL; } user = (struct VSUser*)vs_ctx->users.first; while(user != NULL) { vs_user_free(user); user = user->next; } v_list_free(&vs_ctx->users); #ifdef WITH_OPENSSL vs_destroy_stream_ctx(vs_ctx); #endif }
/** * \brief Free verse client context */ void vc_free_ctx(VC_CTX *vc_ctx) { int i; for(i=0; i<vc_ctx->max_sessions; i++) { if(vc_ctx->vsessions[i]!=NULL) { v_destroy_session(vc_ctx->vsessions[i]); free(vc_ctx->vsessions[i]); vc_ctx->vsessions[i] = NULL; } } free(vc_ctx->ca_path); if(vc_ctx->client_name) free(vc_ctx->client_name); if(vc_ctx->client_version) free(vc_ctx->client_version); }
int32_t vrs_send_connect_request(const char *hostname, const char *service, const uint16_t flags, uint8_t *session_id) { struct VSession *vsession = NULL; uint16 _flags = flags; int already_connected = 0, i, ret; /* Check if CTX was initialized (initialization is done) */ if(vc_ctx == NULL) { v_print_log(VRS_PRINT_ERROR, "Basic callback functions were not set.\n"); return VRS_NO_CB_FUNC; } else { /* Check if all needed callback functions was set up */ if(vc_ctx->vfs.receive_connect_accept == NULL) { v_print_log(VRS_PRINT_ERROR, "receive_connect_accept() callback functions was not set.\n"); return VRS_NO_CB_CONN_FUNC; } if(vc_ctx->vfs.receive_connect_terminate == NULL) { v_print_log(VRS_PRINT_ERROR, "receive_connect_terminate() callback functions was not set.\n"); return VRS_NO_CB_TERM_FUNC; } if(vc_ctx->vfs.receive_user_authenticate == NULL) { v_print_log(VRS_PRINT_ERROR, "receive_user_authenticat() callback functions was not set.\n"); return VRS_NO_CB_USER_AUTH; } } /* Set security protocol */ #if OPENSSL_VERSION_NUMBER >= 0x10000000 /* Check consistency of flags */ if((_flags & VRS_SEC_DATA_NONE) && (_flags & VRS_SEC_DATA_TLS)) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "VRS_SEC_DATA_NONE or VRS_SEC_DATA_TLS could be set, not both.\n"); return VRS_FAILURE; } #else if (_flags & VRS_SEC_DATA_TLS) { v_print_log(VRS_PRINT_WARNING, "flag VRS_SEC_DATA_TLS could be set due to low version of OpenSSL (at least 1.0 is required).\n"); _flags &= ~VRS_SEC_DATA_TLS; _flags |= VRS_SEC_DATA_NONE; } #endif /* Set transport protocol */ if((_flags & VRS_TP_UDP) && (_flags & VRS_TP_TCP)) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "VRS_TP_UDP or VRS_TP_TCP could be set, not both.\n"); return VRS_FAILURE; } else if(!(_flags & VRS_TP_UDP) && !(_flags & VRS_TP_TCP)) { /* When no transport protocol is selected, then use UDP as default */ _flags |= VRS_TP_UDP; } pthread_mutex_lock(&vc_ctx->mutex); /* Check if this client isn't already connected to this server or isn't * trying to connect to the server with hostname:service */ for(i=0; i<vc_ctx->max_sessions; i++) { if(vc_ctx->vsessions[i] != NULL) { if(strcmp(vc_ctx->vsessions[i]->peer_hostname, hostname) == 0 && strcmp(vc_ctx->vsessions[i]->service, service) == 0) { v_print_log(VRS_PRINT_ERROR, "Client already connected to this server.\n"); already_connected = 1; break; } } } if(already_connected == 0) { /* Try to find free verse session slot */ for(i=0; i<vc_ctx->max_sessions; i++) { /* When free VSession slot is found, then create new session */ if(vc_ctx->vsessions[i]==NULL) { vsession = (struct VSession*)malloc(sizeof(struct VSession)); v_init_session(vsession); vsession->peer_hostname = strdup(hostname); vsession->service = strdup(service); /* Copy flags */ vsession->flags = _flags; vsession->in_queue = (struct VInQueue*)calloc(1, sizeof(VInQueue)); v_in_queue_init(vsession->in_queue, IN_QUEUE_DEFAULT_MAX_SIZE); vsession->out_queue = (struct VOutQueue*)calloc(1, sizeof(VOutQueue)); v_out_queue_init(vsession->out_queue, OUT_QUEUE_DEFAULT_MAX_SIZE); vc_ctx->vsessions[i] = vsession; break; } } } pthread_mutex_unlock(&vc_ctx->mutex); if(already_connected == 1) { return VRS_FAILURE; } /* Check if we found free slot for new session */ if(vsession == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "Maximal count of sessions: %d reached.\n", vc_ctx->max_sessions); return VRS_FAILURE; } vsession->session_id = vc_ctx->session_counter++; *session_id = vsession->session_id; /* Try to initialize thread attributes */ if( (ret = pthread_attr_init(&vsession->tcp_thread_attr)) != 0 ) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "pthread_attr_init(): %s\n", strerror(errno)); return VRS_FAILURE; } /* Try to set thread attributes as detached */ if( (ret = pthread_attr_setdetachstate(&vsession->tcp_thread_attr, PTHREAD_CREATE_DETACHED)) != 0) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "pthread_attr_setdetachstate(): %s\n", strerror(errno)); return VRS_FAILURE; } /* Create thread for new client session */ if(pthread_create(&vsession->tcp_thread, &vsession->tcp_thread_attr, vc_new_session_thread, (void*)vsession) != 0) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "Thread creation failed.\n"); pthread_mutex_lock(&vc_ctx->mutex); v_destroy_session(vsession); free(vsession); vc_ctx->vsessions[i] = NULL; pthread_mutex_unlock(&vc_ctx->mutex); return VRS_FAILURE; } /* Destroy thread attributes */ pthread_attr_destroy(&vsession->tcp_thread_attr); return VRS_SUCCESS; }