/** * \brief This function creates new queue for outgoing commands */ struct VOutQueue *v_out_queue_create(void) { struct VOutQueue *out_queue = (struct VOutQueue *)malloc(sizeof(struct VOutQueue)); if(out_queue!=NULL) { if( v_out_queue_init(out_queue, OUT_QUEUE_DEFAULT_MAX_SIZE) != 1) { free(out_queue); out_queue = NULL; } } return out_queue; }
/** * \brief Initialize list of verse sessions */ static int vs_init_sessions(VS_CTX *vs_ctx) { int i; vs_ctx->connected_clients = 0; /* Initialize list of connections */ vs_ctx->vsessions = (struct VSession**)calloc(vs_ctx->max_sessions, sizeof(struct VSession*)); for (i=0; i<vs_ctx->max_sessions; i++) { if( (vs_ctx->vsessions[i] = (struct VSession*)calloc(1, sizeof(struct VSession))) == NULL ) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "calloc(): %s\n", strerror(errno)); return -1; } /* Set up verse session */ v_init_session(vs_ctx->vsessions[i]); /* Set up input and output queues */ vs_ctx->vsessions[i]->in_queue = (struct VInQueue*)calloc(1, sizeof(VInQueue)); v_in_queue_init(vs_ctx->vsessions[i]->in_queue, vs_ctx->in_queue_max_size); vs_ctx->vsessions[i]->out_queue = (struct VOutQueue*)calloc(1, sizeof(VOutQueue)); v_out_queue_init(vs_ctx->vsessions[i]->out_queue, vs_ctx->out_queue_max_size); /* Allocate memory for TCP connection */ vs_ctx->vsessions[i]->stream_conn = (struct VStreamConn*)calloc(1, sizeof(struct VStreamConn)); /* Allocate memory for peer hostname */ vs_ctx->vsessions[i]->peer_hostname = (char*)calloc(INET6_ADDRSTRLEN, sizeof(char)); /* Initialize TCP connection */ vs_init_stream_conn(vs_ctx->vsessions[i]->stream_conn); /* Allocate memory for UDP connection */ vs_ctx->vsessions[i]->dgram_conn = (struct VDgramConn*)calloc(1, sizeof(struct VDgramConn)); /* Initialize UDP connection */ vs_init_dgram_conn(vs_ctx->vsessions[i]->dgram_conn); /* Initialize Avatar ID */ vs_ctx->vsessions[i]->avatar_id = -1; #if defined WITH_PAM /* PAM authentication stuff */ vs_ctx->vsessions[i]->conv.conv = vs_pam_conv; vs_ctx->vsessions[i]->conv.appdata_ptr = NULL; vs_ctx->vsessions[i]->pamh = NULL; #endif } return 1; }
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; }