Esempio n. 1
0
/**
 * \brief Print all system commands in the message to the log file
 */
void v_print_message_sys_cmds(const unsigned char level, const struct VMessage *vmessage)
{
	int i=0;

	while(vmessage->sys_cmd[i].cmd.id != CMD_RESERVED_ID &&
			i < MAX_SYSTEM_COMMAND_COUNT) {
		switch(vmessage->sys_cmd[i].cmd.id) {
		v_print_log_simple(level, "\t");
		case CMD_USER_AUTH_REQUEST:
			v_print_user_auth_request(level,
					(struct User_Authentication_Request*)&vmessage->sys_cmd[i].ua_req);
			break;
		case CMD_USER_AUTH_FAILURE:
			v_print_user_auth_failure(level,
					(struct User_Authentication_Failure*)&vmessage->sys_cmd[i].ua_fail);
			break;
		case CMD_USER_AUTH_SUCCESS:
			v_print_user_auth_success(level,
					(struct User_Authentication_Success*)&vmessage->sys_cmd[i].ua_succ);
			break;
		case CMD_CHANGE_L_ID:
		case CMD_CONFIRM_L_ID:
		case CMD_CHANGE_R_ID:
		case CMD_CONFIRM_R_ID:
			v_print_negotiate_cmd(level,
					(struct Negotiate_Cmd*)&vmessage->sys_cmd[i].negotiate_cmd);
			break;
		}
		v_print_log_simple(level, "\n");
		i++;
	}
}
Esempio n. 2
0
void v_url_print(const int level, struct VURL *url)
{
    v_print_log(level, "URL:\n");
    v_print_log_simple(level, "\tscheme: %s\n", url->scheme);
    /* Print transport protocol */
    if(url->transport_protocol == VRS_TP_UDP) {
        v_print_log_simple(level, "\ttransport_protocol: UDP\n");
    } else if(url->transport_protocol == VRS_TP_TCP) {
        v_print_log_simple(level, "\ttransport_protocol: TCP\n");
    } else if(url->transport_protocol == VRS_TP_WEBSOCKET) {
        v_print_log_simple(level, "\ttransport_protocol: WebSocket\n");
    } else {
        v_print_log_simple(level, "\ttransport_protocol: unknown\n");
    }
    /* Print security protocol */
    if(url->security_protocol == VRS_SEC_DATA_NONE) {
        v_print_log_simple(level, "\tsecurity_protocol: NONE\n");
    } else if(url->security_protocol == VRS_SEC_DATA_TLS) {
        v_print_log_simple(level, "\tsecurity_protocol: DTLS\n");
    } else {
        v_print_log_simple(level, "\tsecurity_protocol: unknown\n");
    }
    /* Print URL */
    v_print_log_simple(level, "\tnode: %s\n", url->node);
    v_print_log_simple(level, "\tservice: %s\n", url->service);
}
Esempio n. 3
0
/**
 * \brief		This function prints history of sent packets
 * \param[in]	*history	The history of sent packets.
 */
void v_print_packet_history(struct VPacket_History *history)
{
	struct VSent_Packet *packet;
	struct VBucket *vbucket;
	int cmd_id;

	v_print_log(VRS_PRINT_DEBUG_MSG, "Packet history:\n\t");
	packet = history->packets.first;
	while(packet!=NULL) {
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "%d, ", packet->id);
		packet = packet->next;
	}
	v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");

	v_print_log(VRS_PRINT_DEBUG_MSG, "Command history:\n");
	for(cmd_id=0; cmd_id<=MAX_CMD_ID; cmd_id++) {
		if(history->cmd_hist[cmd_id] != NULL) {
			vbucket = history->cmd_hist[cmd_id]->cmds.lb.first;
			while(vbucket != NULL) {
				v_cmd_print(VRS_PRINT_DEBUG_MSG, (struct Generic_Cmd*)vbucket->data);
				vbucket = vbucket->next;
			}
		}
	}
}
Esempio n. 4
0
/**
 * \brief This function add command to the head of the queue
 */
int v_out_queue_push_head(struct VOutQueue *out_queue, uint8 prio, struct Generic_Cmd *cmd)
{
	struct VBucket *vbucket;
	int ret = 0;

	/* Lock mutex */
	pthread_mutex_lock(&out_queue->lock);

	/* Try to find command with the same address, when duplicities are not
	 * allowed in command queue */
	if(out_queue->cmds[cmd->id]->flag & REMOVE_HASH_DUPS) {
		vbucket = v_hash_array_find_item(&out_queue->cmds[cmd->id]->cmds, (void*)cmd);
		/* Add command from history of sent command to the outgoing queue
		 * only in situation, when there isn't already newer command in the
		 * queue */
		if(vbucket==NULL) {
			v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\tRe-sending command: %d\n", cmd->id);
			v_cmd_print(VRS_PRINT_DEBUG_MSG, (struct Generic_Cmd*)cmd);

			ret = _v_out_queue_push(out_queue, OUT_QUEUE_ADD_HEAD, prio, cmd);
		}
	} else {
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\tRe-sending command: %d\n", cmd->id);
		v_cmd_print(VRS_PRINT_DEBUG_MSG, (struct Generic_Cmd*)cmd);

		ret = _v_out_queue_push(out_queue, OUT_QUEUE_ADD_HEAD, prio, cmd);
	}

	pthread_mutex_unlock(&out_queue->lock);

	return ret;
}
Esempio n. 5
0
/* Print network address */
void v_print_addr(const unsigned char level, const struct VNetworkAddress *addr)
{
	if(addr->ip_ver==IPV4) {
		char str_addr[INET_ADDRSTRLEN];
		inet_ntop(AF_INET, &(addr->addr.ipv4.sin_addr), str_addr, sizeof(str_addr));
		v_print_log_simple(level, "%s ", str_addr);
	}
	else if(addr->ip_ver==IPV6) {
		char str_addr[INET6_ADDRSTRLEN];
		inet_ntop(AF_INET6, &(addr->addr.ipv6.sin6_addr), str_addr, sizeof(str_addr));
		v_print_log_simple(level, "%s ", str_addr);
	}
}
Esempio n. 6
0
/**
 * \brief This function print content of fake command User_Authenticate
 */
void v_fake_user_auth_print(const unsigned char level, struct User_Authenticate_Cmd *user_auth)
{
	int i;

	v_print_log_simple(level, "\tCONNECT_AUTHENTICATE: username: %s, ",
			user_auth->username);

	if(user_auth->auth_meth_count > 0) {
		v_print_log_simple(level, "methods: ");
		for(i=0; i<user_auth->auth_meth_count; i++) {
			switch(user_auth->methods[i]) {
			case VRS_UA_METHOD_NONE:
				v_print_log_simple(level, "NONE, ");
				break;
			case VRS_UA_METHOD_PASSWORD:
				v_print_log_simple(level, "PASSWORD, ");
				break;
			case VRS_UA_METHOD_RESERVED:
				v_print_log_simple(level, "RESERVED, ");
				break;
			default:
				v_print_log_simple(level, "Unknown, ");
				break;
			}
		}
	}

	if(user_auth->data != NULL) {
		v_print_log_simple(level, "data: %s", user_auth->data);
	}

	v_print_log_simple(level, "\n");
}
Esempio n. 7
0
/**
 * \brief This function print content of fake command Tag_Create_Ack.
 */
void v_fake_tag_create_ack_print(const unsigned char level,
                                 const struct Generic_Cmd *cmd)
{
    struct Tag_Create_Ack_Cmd *tag_create_ack = (struct Tag_Create_Ack_Cmd *)cmd;
    v_print_log_simple(level, "\tTag_Create_Ack: Node_ID: %d, TagGroup_ID: %d, Tag_ID %d\n",
                       tag_create_ack->node_id, tag_create_ack->taggroup_id, tag_create_ack->tag_id);
}
Esempio n. 8
0
void v_print_receive_message(struct vContext *C)
{
	struct IO_CTX *io_ctx = CTX_io_ctx(C);
	struct VMessage *r_message = CTX_r_message(C);

	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		printf("%c[%d;%dm", 27, 1, 34);
		v_print_log(VRS_PRINT_DEBUG_MSG, "Receive message: ");
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "Socket: %d, ", io_ctx->sockfd);
		v_print_addr_port(VRS_PRINT_DEBUG_MSG, &io_ctx->peer_addr);
		v_print_message_header(VRS_PRINT_DEBUG_MSG, r_message);
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
		v_print_message_sys_cmds(VRS_PRINT_DEBUG_MSG, r_message);
		printf("%c[%dm", 27, 0);
	}
}
Esempio n. 9
0
/**
 * \brief This function prints content of fake command Layer_Destroy_Ack.
 */
void v_fake_layer_destroy_ack_print(const unsigned char level,
		const struct Generic_Cmd *cmd)
{
	struct Layer_Destroy_Ack_Cmd *layer_destroy_ack = (struct Layer_Destroy_Ack_Cmd *)cmd;
	v_print_log_simple(level, "\tLayer_Destroy_Ack: Node_ID: %d, Layer_ID: %d\n",
			layer_destroy_ack->node_id,
			layer_destroy_ack->layer_id);
}
Esempio n. 10
0
/* Print network address and port */
void v_print_addr_port(const unsigned char level, const struct VNetworkAddress *addr)
{
	unsigned short port;

	if(addr->ip_ver==IPV4) {
		char str_addr[INET_ADDRSTRLEN];
		inet_ntop(AF_INET, &(addr->addr.ipv4.sin_addr), str_addr, sizeof(str_addr));
		port = ntohs(addr->addr.ipv4.sin_port);
		v_print_log_simple(level, "%s:%d ", str_addr, port);
	}
	else if(addr->ip_ver==IPV6) {
		char str_addr[INET6_ADDRSTRLEN];
		inet_ntop(AF_INET6, &(addr->addr.ipv6.sin6_addr), str_addr, sizeof(str_addr));
		port = ntohs(addr->addr.ipv6.sin6_port);
		v_print_log_simple(level, "[%s]:%d ", str_addr, port);
	}
}
Esempio n. 11
0
/**
 * \brief This function prints content of the USER_AUTH_FAILURE command
 */
void v_print_user_auth_failure(const unsigned char level, struct User_Authentication_Failure *ua_fail)
{
	int i;

	v_print_log_simple(level, "\tUSER_AUTH_FAILURE, ");

	if(ua_fail->count>0) {
		v_print_log_simple(level, "Methods: ");
		for(i=0; i<ua_fail->count; i++) {
			switch(ua_fail->method[i]) {
				case VRS_UA_METHOD_RESERVED:
					v_print_log_simple(level, "Reserved, ");
					break;
				case VRS_UA_METHOD_NONE:
					v_print_log_simple(level, "None, ");
					break;
				case VRS_UA_METHOD_PASSWORD:
					v_print_log_simple(level, "Password, ");
					break;
			}
		}
	} else {
		v_print_log_simple(level, "Access not granted.");
	}
	v_print_log_simple(level, "\n");
}
Esempio n. 12
0
/**
 * \brief Print verse packet header to the log file
 */
void v_print_packet_header(const unsigned char level, const VPacket *vpacket)
{
	int i;

	v_print_log_simple(level, "Ver: %d, Flags: ", vpacket->header.version);
	for(i=7; i>=0; i--) {
		if((1<<i) & vpacket->header.flags) {
			switch (1<<i) {
				case PAY_FLAG:
					v_print_log_simple(level, "PAY,");
					break;
				case ACK_FLAG:
					v_print_log_simple(level, "ACK,");
					break;
				case ANK_FLAG:
					v_print_log_simple(level, "ANK,");
					break;
				case SYN_FLAG:
					v_print_log_simple(level, "SYN,");
					break;
				case FIN_FLAG:
					v_print_log_simple(level, "FIN,");
					break;
			}
		}
	}
	v_print_log_simple(level, " Window:%d, PayID:%d, AckNakID:%d, AnkID:%d\n",
			vpacket->header.window, vpacket->header.payload_id,
			vpacket->header.ack_nak_id, vpacket->header.ank_id);
}
Esempio n. 13
0
void v_print_receive_packet(struct vContext *C)
{
	struct IO_CTX *io_ctx = CTX_io_ctx(C);
	struct VDgramConn *dgram_conn = CTX_current_dgram_conn(C);
	struct VPacket *r_packet = CTX_r_packet(C);

	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		printf("%c[%d;%dm", 27, 1, 34);
		v_print_log(VRS_PRINT_DEBUG_MSG, "Receive packet: ");
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "Socket: %d, ", io_ctx->sockfd);
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "bufsize: %d, ", io_ctx->buf_size);
		v_print_addr_port(VRS_PRINT_DEBUG_MSG, &io_ctx->peer_addr);
		v_print_packet_header(VRS_PRINT_DEBUG_MSG, r_packet);
		v_print_log(VRS_PRINT_DEBUG_MSG, "Shift: %d -> Window: %d\n", dgram_conn->rwin_host_scale, (unsigned int)r_packet->header.window << dgram_conn->rwin_host_scale);
		v_print_packet_sys_cmds(VRS_PRINT_DEBUG_MSG, r_packet);
		printf("%c[%dm", 27, 0);
	}
}
Esempio n. 14
0
/* Clear datagram connection */
void v_conn_dgram_clear(struct VDgramConn *dgram_conn)
{
	/* Debug print */
	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "Free connection ");
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "%d ", dgram_conn->host_id);
		v_print_addr_port(VRS_PRINT_DEBUG_MSG, &dgram_conn->peer_address);
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
	}

#ifdef WITH_OPENSSL
	if(dgram_conn->io_ctx.bio != NULL) {
		BIO_vfree(dgram_conn->io_ctx.bio);
		dgram_conn->io_ctx.bio = NULL;
	}
#endif

	close(dgram_conn->io_ctx.sockfd);

	v_conn_dgram_init(dgram_conn);
}
Esempio n. 15
0
/* Destroy datagram connection */
void v_conn_dgram_destroy(struct VDgramConn *dgram_conn)
{
	/* Debug print */
	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "Free connection ");
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "%d ", dgram_conn->host_id);
		v_print_addr_port(VRS_PRINT_DEBUG_MSG, &dgram_conn->peer_address);
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
	}

	if(dgram_conn->io_ctx.buf) {
		free(dgram_conn->io_ctx.buf);
		dgram_conn->io_ctx.buf = NULL;
	}

	v_packet_history_destroy(&dgram_conn->packet_history);

	v_ack_nak_history_clear(&dgram_conn->ack_nak);

	close(dgram_conn->io_ctx.sockfd);
}
Esempio n. 16
0
void v_url_print(const int level, struct VURL *url)
{
	v_print_log(level, "URL:\n");
	v_print_log_simple(level, "\tscheme: %s\n", url->scheme);
	if(url->transport_protocol==VRS_TP_UDP) {
		v_print_log_simple(level, "\tdgram_protocol: UDP\n");
	} else {
		v_print_log_simple(level, "\tdgram_protocol: unknow\n");
	}
	if(url->security_protocol==VRS_SEC_DATA_NONE) {
		v_print_log_simple(level, "\tsecurity_protocol: NONE\n");
	} else if(url->security_protocol==VRS_SEC_DATA_TLS) {
		v_print_log_simple(level, "\tsecurity_protocol: DTLS\n");
	} else {
		v_print_log_simple(level, "\tsecurity_protocol: unknown\n");
	}
	v_print_log_simple(level, "\tnode: %s\n", url->node);
	v_print_log_simple(level, "\tservice: %s\n", url->service);
}
Esempio n. 17
0
/**
 * \brief This function prints negotiate commands: Change_L/R and Confirm_L/R
 */
void v_print_negotiate_cmd(const unsigned char level, struct Negotiate_Cmd *negotiate_cmd)
{
	int i;

	switch(negotiate_cmd->id) {
		case CMD_CHANGE_L_ID:
			v_print_log_simple(level, "\tCHANGE_L COMMAND, ");
			break;
		case CMD_CONFIRM_L_ID:
			v_print_log_simple(level, "\tCONFIRM_L COMMAND, ");
			break;
		case CMD_CHANGE_R_ID:
			v_print_log_simple(level, "\tCHANGE_R COMMAND, ");
			break;
		case CMD_CONFIRM_R_ID:
			v_print_log_simple(level, "\tCONFIRM_R COMMAND, ");
			break;
		default:
			v_print_log_simple(level, "\tNEGOTIATE DEBUG PRINT ERROR: bad command id\n");
			break;
	}

	v_print_log_simple(level, "count: %d, ", negotiate_cmd->count);
	switch(negotiate_cmd->feature) {
		case FTR_FC_ID:
			v_print_log_simple(level, "feature: FC_ID, ");
			break;
		case FTR_CC_ID:
			v_print_log_simple(level, "feature: CC_ID, ");
			break;
		case FTR_HOST_URL:
			v_print_log_simple(level, "feature: HOST_URL, ");
			break;
		case FTR_TOKEN:
			v_print_log_simple(level, "feature: TOKEN, ");
			break;
		case FTR_DED:
			v_print_log_simple(level, "feature: DED, ");
			break;
		case FTR_RWIN_SCALE:
			v_print_log_simple(level, "feature: RWIN_SCALE, ");
			break;
		case FTR_FPS:
			v_print_log_simple(level, "feature: FPS, ");
			break;
		case FTR_CMD_COMPRESS:
			v_print_log_simple(level, "feature: CMD_COMPRESS, ");
			break;
		case FTR_CLIENT_NAME:
			v_print_log_simple(level, "feature: CLIENT_NAME, ");
			break;
		case FTR_CLIENT_VERSION:
			v_print_log_simple(level, "feature: CLIENT_VERSION, ");
			break;
		default:
			v_print_log_simple(level, "unknown feature, ");
			break;
	}

	for(i=0; i<negotiate_cmd->count; i++) {
		switch(negotiate_cmd->feature) {
			case FTR_FC_ID:
			case FTR_CC_ID:
			case FTR_RWIN_SCALE:
			case FTR_CMD_COMPRESS:
				v_print_log_simple(level, "%d, ",
						negotiate_cmd->value[i].uint8);
				break;
			case FTR_HOST_URL:
			case FTR_TOKEN:
			case FTR_DED:
			case FTR_CLIENT_NAME:
			case FTR_CLIENT_VERSION:
				v_print_log_simple(level, "%d:%s, ",
						negotiate_cmd->value[i].string8.length,
						negotiate_cmd->value[i].string8.str);
				break;
			case FTR_FPS:
				v_print_log_simple(level, "%6.3f, ",
						negotiate_cmd->value[i].real32);
				break;
			default:
				break;
		}
	}
	v_print_log_simple(level, "\n");
}
Esempio n. 18
0
/**
 * \brief This function print content of fake command Connect_Terminate
 */
void v_fake_connect_terminate_print(const unsigned char level, struct Connect_Terminate_Cmd *connect_terminate)
{
	v_print_log_simple(level, "\tCONNECT_TERMINATE: error: %d\n",
			connect_terminate->error_num);
}
Esempio n. 19
0
/**
 * \brief This connection tries to handle new connection attempt. When this
 * attempt is successful, then it creates new thread
 */
static int vs_new_stream_conn(struct vContext *C, void *(*conn_loop)(void*))
{
	VS_CTX *vs_ctx = CTX_server_ctx(C);
	struct IO_CTX *io_ctx = CTX_io_ctx(C);
	struct VSession *current_session = NULL;
	socklen_t addr_len;
	int ret, i;
	static uint32 last_session_id = 0;

	/* Try to find free session */
	for(i=0; i< vs_ctx->max_sessions; i++) {
		if(vs_ctx->vsessions[i]->stream_conn->host_state == TCP_SERVER_STATE_LISTEN) {
			/* TODO: lock mutex here */
			current_session = vs_ctx->vsessions[i];
			current_session->stream_conn->host_state = TCP_SERVER_STATE_RESPOND_METHODS;
			current_session->session_id = last_session_id++;
			/* TODO: unlock mutex here */
			break;
		}
	}

	if(current_session != NULL) {
		struct vContext *new_C;
		int flag;

		/* Try to accept client connection (do TCP handshake) */
		if(io_ctx->host_addr.ip_ver==IPV4) {
			/* Prepare IPv4 variables for TCP handshake */
			struct sockaddr_in *client_addr4 = &current_session->stream_conn->io_ctx.peer_addr.addr.ipv4;
			current_session->stream_conn->io_ctx.peer_addr.ip_ver = IPV4;
			addr_len = sizeof(current_session->stream_conn->io_ctx.peer_addr.addr.ipv4);

			/* Try to do TCP handshake */
			if( (current_session->stream_conn->io_ctx.sockfd = accept(io_ctx->sockfd, (struct sockaddr*)client_addr4, &addr_len)) == -1) {
				if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "accept(): %s\n", strerror(errno));
				return 0;
			}

			/* Save the IPv4 of the client as string in verse session */
			inet_ntop(AF_INET, &client_addr4->sin_addr, current_session->peer_hostname, INET_ADDRSTRLEN);
		} else if(io_ctx->host_addr.ip_ver==IPV6) {
			/* Prepare IPv6 variables for TCP handshake */
			struct sockaddr_in6 *client_addr6 = &current_session->stream_conn->io_ctx.peer_addr.addr.ipv6;
			current_session->stream_conn->io_ctx.peer_addr.ip_ver = IPV6;
			addr_len = sizeof(current_session->stream_conn->io_ctx.peer_addr.addr.ipv6);

			/* Try to do TCP handshake */
			if( (current_session->stream_conn->io_ctx.sockfd = accept(io_ctx->sockfd, (struct sockaddr*)client_addr6, &addr_len)) == -1) {
				if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "accept(): %s\n", strerror(errno));
				return 0;
			}

			/* Save the IPv6 of the client as string in verse session */
			inet_ntop(AF_INET6, &client_addr6->sin6_addr, current_session->peer_hostname, INET6_ADDRSTRLEN);
		}

		/* Set to this socket flag "no delay" */
		flag = 1;
		if(setsockopt(current_session->stream_conn->io_ctx.sockfd,
				IPPROTO_TCP, TCP_NODELAY, &flag, (socklen_t)sizeof(flag)) == -1)
		{
			if(is_log_level(VRS_PRINT_ERROR)) {
				v_print_log(VRS_PRINT_ERROR,
						"setsockopt: TCP_NODELAY: %d\n",
						strerror(errno));
			}
			return -1;;
		}

		CTX_current_session_set(C, current_session);
		CTX_current_stream_conn_set(C, current_session->stream_conn);
		CTX_io_ctx_set(C, &current_session->stream_conn->io_ctx);

		if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
			v_print_log(VRS_PRINT_DEBUG_MSG, "New connection from: ");
			v_print_addr_port(VRS_PRINT_DEBUG_MSG, &(current_session->stream_conn->io_ctx.peer_addr));
			v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
		}

		/* Duplicate verse context for new thread */
		new_C = (struct vContext*)calloc(1, sizeof(struct vContext));
		memcpy(new_C, C, sizeof(struct vContext));

		/* Try to initialize thread attributes */
		if( (ret = pthread_attr_init(&current_session->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 0;
		}

		/* Try to set thread attributes as detached */
		if( (ret = pthread_attr_setdetachstate(&current_session->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 0;
		}

		/* Try to create new thread */
		if((ret = pthread_create(&current_session->tcp_thread, &current_session->tcp_thread_attr, conn_loop, (void*)new_C)) != 0) {
			if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "pthread_create(): %s\n", strerror(errno));
		}

		/* Destroy thread attributes */
		pthread_attr_destroy(&current_session->tcp_thread_attr);
	} else {
		int tmp_sockfd;
		v_print_log(VRS_PRINT_DEBUG_MSG, "Number of session slot: %d reached\n", vs_ctx->max_sessions);
		/* TODO: return some error. Not only accept and close connection. */
		/* Try to accept client connection (do TCP handshake) */
		if(io_ctx->host_addr.ip_ver == IPV4) {
			/* Prepare IP6 variables for TCP handshake */
			struct sockaddr_in client_addr4;

			addr_len = sizeof(client_addr4);

			/* Try to do TCP handshake */
			if( (tmp_sockfd = accept(io_ctx->sockfd, (struct sockaddr*)&client_addr4, &addr_len)) == -1) {
				if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "accept(): %s\n", strerror(errno));
				return 0;
			}
			/* Close connection (no more free session slots) */
			close(tmp_sockfd);
		} else if(io_ctx->host_addr.ip_ver == IPV6) {
			/* Prepare IP6 variables for TCP handshake */
			struct sockaddr_in6 client_addr6;
			addr_len = sizeof(client_addr6);

			/* Try to do TCP handshake */
			if( (tmp_sockfd = accept(io_ctx->sockfd, (struct sockaddr*)&client_addr6, &addr_len)) == -1) {
				if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "accept(): %s\n", strerror(errno));
				return 0;
			}
			/* Close connection (no more free session slots) */
			close(tmp_sockfd);
		}
		/* TODO: Fix this */
		sleep(1);
	}

	return 1;
}
Esempio n. 20
0
/**
 * \brief Print verse message header to the log file
 */
void v_print_message_header(const unsigned char level, const VMessage *vmessage)
{
	v_print_log_simple(level, "Ver: %d, Len: %d", vmessage->header.version, vmessage->header.len);
}
Esempio n. 21
0
/**
 * \brief Main Verse server loop. Server waits for connect attempts, responds to attempts
 * and creates per connection threads
 */
int vs_main_listen_loop(VS_CTX *vs_ctx)
{
	struct vContext *C;
	struct timeval start, tv;
	fd_set set;
	int count, tmp, i, ret;
	int sockfd;

	/* Allocate context for server */
	C = (struct vContext*)calloc(1, sizeof(struct vContext));
	/* Set up client context, connection context and IO context */
	CTX_server_ctx_set(C, vs_ctx);
	CTX_client_ctx_set(C, NULL);
	CTX_current_dgram_conn_set(C, NULL);

	/* Get time of the start of the server */
	gettimeofday(&start, NULL);

	/* Seed random number generator */
#ifdef __APPLE__
	sranddev();
	/* Other BSD based systems probably support this or similar function too. */
#else
	/* Other systems have to use this evil trick */
	srand(start.tv_sec - start.tv_usec);
#endif

	/* "Never ending" listen loop */
	while(vs_ctx->state == SERVER_STATE_READY) {
		/* Debug print */
		gettimeofday(&tv, NULL);
		if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
			if(tv.tv_sec==start.tv_sec)
				v_print_log(VRS_PRINT_DEBUG_MSG, "\t+0s");
			else
				v_print_log(VRS_PRINT_DEBUG_MSG, "\t+%lds", (long int)(tv.tv_sec - start.tv_sec));
#ifdef WSLAY
			v_print_log_simple(VRS_PRINT_DEBUG_MSG,
					"\tServer listen on (TCP port: %d, WebSocket port: %d)\n",
					vs_ctx->tcp_io_ctx.host_addr.port,
					vs_ctx->ws_io_ctx.host_addr.port);
#else
			v_print_log_simple(VRS_PRINT_DEBUG_MSG,
					"\tServer listen on TCP port: %d\n",
					vs_ctx->tcp_io_ctx.host_addr.port);
#endif
		}

		/* Set up set of sockets */
		FD_ZERO(&set);
		FD_SET(vs_ctx->tcp_io_ctx.sockfd, &set);
		/* When Verse is compiled with support of WebSocket, then listen on
		 * WebSocket port too */
#ifdef WSLAY
		FD_SET(vs_ctx->ws_io_ctx.sockfd, &set);
		sockfd = (vs_ctx->tcp_io_ctx.sockfd > vs_ctx->ws_io_ctx.sockfd) ?
				vs_ctx->tcp_io_ctx.sockfd : vs_ctx->ws_io_ctx.sockfd;
#else
		sockfd = vs_ctx->tcp_io_ctx.sockfd;
#endif

		/* We will wait one second for connect attempt, then debug print will
		 * be print again */
		tv.tv_sec = 1;
		tv.tv_usec = 0;


		/* Wait for event on listening sockets */
		if( (ret = select(sockfd+1, &set, NULL, NULL, &tv)) == -1 ) {
			int err = errno;
			if(err==EINTR) {
				break;
			} else {
				if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR,
						"%s:%s():%d select(): %s\n",
						__FILE__,
						__FUNCTION__,
						__LINE__,
						strerror(err));
				return -1;
			}
			/* Was event on the listen socket */
		} else if(ret>0) {
			if (FD_ISSET(vs_ctx->tcp_io_ctx.sockfd, &set))
			{
				v_print_log(VRS_PRINT_DEBUG_MSG, "TCP Connection attempt\n");
				CTX_io_ctx_set(C, &vs_ctx->tcp_io_ctx);
				vs_new_stream_conn(C, vs_tcp_conn_loop);
#ifdef WSLAY
			} else if(FD_ISSET(vs_ctx->ws_io_ctx.sockfd, &set)) {
				v_print_log(VRS_PRINT_DEBUG_MSG, "WebSocket Connection attempt\n");
				CTX_io_ctx_set(C, &vs_ctx->ws_io_ctx);
				vs_new_stream_conn(C, vs_websocket_loop);
#endif
			}
		}
	}

	count = 0;
	while( (vs_ctx->state == SERVER_STATE_CLOSING) && (count < VRS_TIMEOUT) ) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "Wait for Server state CLOSED\n");

		/* Check if there are still some pending connection */
		tmp = 0;
		for(i=0; i<vs_ctx->max_sessions; i++) {
			if(vs_ctx->vsessions[i] != NULL) {
				if(vs_ctx->vsessions[i]->stream_conn != NULL &&
					vs_ctx->vsessions[i]->stream_conn->host_state != TCP_SERVER_STATE_LISTEN ) {
					tmp++;
				}
				/* TODO: cancel thread with closed connection to speed up server exit
					pthread_kill(vs_ctx->vsessions[i]->tcp_thread, SIGALRM);
					pthread_join(vs_ctx->vsessions[i]->tcp_thread, NULL);
				*/

			}
		}
		if(tmp==0) {
			vs_ctx->state = SERVER_STATE_CLOSED;
		} else {
			sleep(1);
		}
	}

	free(C);

	return 1;
}
Esempio n. 22
0
/**
 * \brief Load configuration from file to the Verse server context.
 *
 * \param	vs_ctx	The Verse server context.
 * \param	file	The pointer at FILE structure;
 */
void vs_read_config_file(struct VS_CTX *vs_ctx, const char *ini_file_name)
{
	dictionary *ini_dict;

	ini_dict = iniparser_load((char*) ini_file_name);

	if(ini_dict != NULL) {
		char *user_auth_method;
		char *certificate_file_name;
		char *ca_certificate_file_name;
		char *private_key;
		char *fc_type;
#ifdef WITH_MONGODB
		char *mongodb_server_hostname;
		int mongodb_server_port;
		char *mongodb_server_db_name;
		char *mongodb_user;
		char *mongodb_pass;
#endif
		int fc_win_scale;
		int in_queue_max_size;
		int out_queue_max_size;
		int tcp_port_number;
		int ws_port_number;
		int udp_low_port_number;
		int udp_high_port_number;
		int max_session_count;

		v_print_log(VRS_PRINT_DEBUG_MSG, "Reading config file: %s\n",
				ini_file_name);

#ifdef WITH_OPENSSL
		/* Try to get TLS port number */
		tcp_port_number = iniparser_getint(ini_dict, "Global:TLS_port", -1);
		if(tcp_port_number != -1) {
			if(tcp_port_number >= 1024 && tcp_port_number <= 65535) {
				vs_ctx->tcp_port = tcp_port_number;
			} else {
				v_print_log(VRS_PRINT_WARNING, "TLS port: %d out of range: 1024-65535\n",
						tcp_port_number);
			}
		}
#else
		/* Try to get TCP port number */
		tcp_port_number = iniparser_getint(ini_dict, "Global:TCP_port", -1);
		if(tcp_port_number != -1) {
			if(tcp_port_number >= 1024 && tcp_port_number <= 65535) {
				vs_ctx->tcp_port = tcp_port_number;
			} else {
				v_print_log(VRS_PRINT_WARNING, "TCP port: %d out of range: 1024-65535\n",
						tcp_port_number);
			}
		}
#endif

		/* Try to get WebSocket port number */
		ws_port_number = iniparser_getint(ini_dict, "Global:WS_port", -1);
		if(ws_port_number != -1) {
			if(ws_port_number >= 1024 && ws_port_number <= 65535) {
				vs_ctx->ws_port = ws_port_number;
			} else {
				v_print_log(VRS_PRINT_WARNING, "WebSocket port: %d out of range: 1024-65535\n",
						ws_port_number);
			}
		}

		/* Try to get lowest UDP port */
		udp_low_port_number = iniparser_getint(ini_dict, "Global:UDP_port_low", -1);
		if(udp_low_port_number != -1) {
			if(udp_low_port_number >= 49152 && udp_low_port_number <= 65535) {
				vs_ctx->port_low = udp_low_port_number;
			} else {
				v_print_log(VRS_PRINT_WARNING, "UDP port: %d out of range: 49152-65535\n",
						udp_low_port_number);
			}
		}

		udp_high_port_number = iniparser_getint(ini_dict, "Global:UDP_port_high", -1);
		if(udp_high_port_number != -1) {
			if(udp_high_port_number >= 49152 && udp_high_port_number <= 65535) {
				vs_ctx->port_high = udp_high_port_number;
			} else {
				v_print_log(VRS_PRINT_WARNING, "UDP port: %d out of range: 49152-65535\n",
						udp_high_port_number);
			}
		}

		max_session_count = iniparser_getint(ini_dict, "Global:MaxSessionCount", -1);
		if(max_session_count != -1) {
			vs_ctx->max_sessions = max_session_count;
		}

		/* Try to load section [Users] */
		user_auth_method = iniparser_getstring(ini_dict, "Users:Method", NULL);
		if(user_auth_method != NULL &&
				strcmp(user_auth_method, "file") == 0)
		{
			char *file_type;

			v_print_log(VRS_PRINT_DEBUG_MSG, "user_auth_method: %s\n", user_auth_method);

			file_type = iniparser_getstring(ini_dict, "Users:FileType", NULL);

			if(file_type != NULL &&
					strcmp(file_type, "csv") == 0)
			{
				char *csv_file_name;

				v_print_log(VRS_PRINT_DEBUG_MSG, "file_type: %s\n", file_type);

				csv_file_name = iniparser_getstring(ini_dict, "Users:File", NULL);

				if(csv_file_name !=NULL) {
					vs_ctx->auth_type = AUTH_METHOD_CSV_FILE;
					if(vs_ctx->csv_user_file != NULL) {
						free(vs_ctx->csv_user_file);
					}
					vs_ctx->csv_user_file = strdup(csv_file_name);
					v_print_log(VRS_PRINT_DEBUG_MSG,
							"csv_file_name: %s\n", csv_file_name);
				}
			}
		}

		/* Try to load section [Security] */
		certificate_file_name = iniparser_getstring(ini_dict, "Security:Certificate", NULL);
		if(certificate_file_name != NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"certificate_file_name: %s\n", certificate_file_name);
			if(vs_ctx->public_cert_file != NULL) {
				free(vs_ctx->public_cert_file);
			}
			vs_ctx->public_cert_file = strdup(certificate_file_name);
		}

		/* Certificate of certificate authority */
		ca_certificate_file_name = iniparser_getstring(ini_dict, "Security:CACertificate", NULL);
		if(ca_certificate_file_name != NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"ca_certificate_file_name: %s\n", ca_certificate_file_name);
			vs_ctx->ca_cert_file = strdup(ca_certificate_file_name);
		}

		/* Server private key */
		private_key = iniparser_getstring(ini_dict, "Security:PrivateKey", NULL);
		if(private_key != NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"private_key: %s\n", private_key);
			if(vs_ctx->private_cert_file != NULL) {
				free(vs_ctx->private_cert_file);
			}
			vs_ctx->private_cert_file = strdup(private_key);
		}

		/* Type of Flow Control */
		fc_type = iniparser_getstring(ini_dict, "FlowControl:Type", NULL);
		if(fc_type != NULL) {
			if(strcmp(fc_type, "tcp_like")==0) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"flow_control: %s\n", fc_type);
				vs_ctx->fc_meth = FC_TCP_LIKE;
			} else if(strcmp(fc_type, "none")==0) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"flow_control type: %s\n", fc_type);
				vs_ctx->fc_meth = FC_NONE;
			}
		}

		/* Scale of Flow Control window */
		fc_win_scale = iniparser_getint(ini_dict, "FlowControl:WinScale", -1);
		if(fc_win_scale != -1) {
			if(fc_win_scale >= 0 && fc_win_scale <= 255) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"flow_control scale: %d\n", fc_win_scale);
				vs_ctx->rwin_scale = fc_win_scale;
			}
		}

		/* Maximal size of incoming queue */
		in_queue_max_size = iniparser_getint(ini_dict, "InQueue:MaxSize", -1);
		if(in_queue_max_size != -1) {
			if(in_queue_max_size > 0) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"in_queue max size: %d\n", in_queue_max_size);
				vs_ctx->in_queue_max_size = in_queue_max_size;
			}
		}

		/* Maximal size of outgoing queue */
		out_queue_max_size = iniparser_getint(ini_dict, "OutQueue:MaxSize", -1);
		if(out_queue_max_size != -1) {
			if(out_queue_max_size > 0) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"in_queue max size: %d\n", out_queue_max_size);
				vs_ctx->in_queue_max_size = out_queue_max_size;
			}
		}
#ifdef WITH_MONGODB
		/* Hostname of MongoDB server */
		mongodb_server_hostname = iniparser_getstring(ini_dict,
				"MongoDB:ServerHostname", NULL);
		if(mongodb_server_hostname != NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"mongodb server hostname: %s\n", mongodb_server_hostname);
			vs_ctx->mongodb_server = strdup(mongodb_server_hostname);
		}

		/* Port of MongoDB server */
		mongodb_server_port = iniparser_getint(ini_dict,
				"MongoDB:ServerPort", -1);
		if(mongodb_server_port != -1) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"mongodb server port: %d\n", mongodb_server_port);
			vs_ctx->mongodb_port = mongodb_server_port;
		}

		/* MongoDB database name used by Verse server */
		mongodb_server_db_name = iniparser_getstring(ini_dict,
				"MongoDB:DatabaseName", NULL);
		if(mongodb_server_db_name != NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"mongodb server database name: %s\n", mongodb_server_db_name);
			vs_ctx->mongodb_db_name = strdup(mongodb_server_db_name);
		}

		/* Username used for authentication at MongoDB */
		mongodb_user = iniparser_getstring(ini_dict,
				"MongoDB:Username", NULL);
		if(mongodb_user != NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG, "mongodb server username: %s\n",
					mongodb_user);
			vs_ctx->mongodb_user = strdup(mongodb_user);
		}

		/* Password used for authentication at MongoDB */
		mongodb_pass = iniparser_getstring(ini_dict,
				"MongoDB:Password", NULL);
		if(mongodb_user != NULL) {
			int i;
			v_print_log(VRS_PRINT_DEBUG_MSG, "mongodb server password: "******"*");
			}
			v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
			vs_ctx->mongodb_pass = strdup(mongodb_pass);
		}
#endif

		iniparser_freedict(ini_dict);
	} else {
		v_print_log(VRS_PRINT_WARNING, "Unable to load config file: %s\n",
				ini_file_name);
	}
}
Esempio n. 23
0
/**
 * \brief WebSocket callback function for received message
 */
void vs_ws_recv_msg_callback(wslay_event_context_ptr wslay_ctx,
		const struct wslay_event_on_msg_recv_arg *arg,
		void *user_data)
{
	struct vContext *C = (struct vContext*)user_data;
	struct VS_CTX *vs_ctx = CTX_server_ctx(C);
	struct VSession *session = CTX_current_session(C);
	struct IO_CTX *io_ctx = CTX_io_ctx(C);
	int ret;

	if(!wslay_is_ctrl_frame(arg->opcode)) {

		/* Verse server uses only binary message for communication */
		if(arg->opcode == WSLAY_BINARY_FRAME) {
		    struct wslay_event_msg msgarg;

#if DEBUG_WEB_SOCKET
		    unsigned int i;

			v_print_log(VRS_PRINT_DEBUG_MSG,
					"WS Callback received binary message\n");

			v_print_log(VRS_PRINT_DEBUG_MSG,
					"Binary dump\n");

			/* Print dump of received data */
			for(i=0; i<arg->msg_length; i++) {
				v_print_log_simple(VRS_PRINT_DEBUG_MSG, "%d,", arg->msg[i]);
			}
			v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
#endif

			/* Copy received data to IO context */
			memcpy(io_ctx->buf,	arg->msg, arg->msg_length);
			io_ctx->buf_size = arg->msg_length;

			if(session->stream_conn->host_state == TCP_SERVER_STATE_STREAM_OPEN) {
				if(v_STREAM_handle_messages(C) != 0) {
					/* When some payload data were received, then poke data thread */
					sem_post(vs_ctx->data.sem);
				} else {
					/* End connection */
					session->stream_conn->host_state = TCP_SERVER_STATE_CLOSING;

					/* Try to close connection with WebSocket client */
					wslay_event_queue_close(wslay_ctx,
							WSLAY_CODE_PROTOCOL_ERROR,
							(uint8_t*)"Wrong command",	/* Close message */
							13);	/* The length of close message */
					return;
				}
			} else {
				if( vs_handle_handshake(C) == -1 ) {
					/* End connection */
					session->stream_conn->host_state = TCP_SERVER_STATE_CLOSING;

					/* Try to close connection with WebSocket client */
					wslay_event_queue_close(wslay_ctx,
							WSLAY_CODE_PROTOCOL_ERROR,
							(uint8_t*)"Wrong command",	/* Close message */
							13);	/* The length of close message */
					return;
				}

				/* During handshake send response immediately. */

				/* TODO: optionally send message fragmented, when it is needed using:
				 * wslay_event_queue_fragmented_msg() */
				msgarg.opcode = WSLAY_BINARY_FRAME;
				msgarg.msg = (uint8_t*)io_ctx->buf;
				msgarg.msg_length = io_ctx->buf_size;

				/* Queue message for sending */
				if((ret = wslay_event_queue_msg(wslay_ctx, &msgarg)) != 0) {
					v_print_log(VRS_PRINT_ERROR,
							"Unable to queue message to WebSocket: %d\n", ret);
					return;
				} else {
					v_print_log(VRS_PRINT_DEBUG_MSG,
							"WebSocket message successfully queued\n");
				}
			}

		} else if(arg->opcode == WSLAY_TEXT_FRAME) {
			v_print_log(VRS_PRINT_ERROR, "WebSocket text frame is not supported\n");
			return;
		}

	} else {
		/* Print opcode of control message */
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"WS Callback Received Ctrl Message: opcode: %d\n",
				arg->opcode);

		/* Is it closing message? */
		if(arg->opcode & WSLAY_CONNECTION_CLOSE) {

			v_print_log(VRS_PRINT_DEBUG_MSG,
					"Close message with code: %d, message: %s\n",
					arg->status_code,
					arg->msg);

			/* When this control message was received at second time, then
			 * switch to the state CLOSED. Otherwise switch to the state
			 * CLOSING */
			if(session->stream_conn->host_state == TCP_SERVER_STATE_CLOSING) {
				session->stream_conn->host_state = TCP_SERVER_STATE_CLOSED;
			} else {
				session->stream_conn->host_state = TCP_SERVER_STATE_CLOSING;
				/* When server wasn't in the state closing, then send
				 * confirmation to the client, that this connection will be
				 * closed */
				wslay_event_queue_close(wslay_ctx,
						WSLAY_CODE_NORMAL_CLOSURE,
						(uint8_t*)"Closing connection",
						15);
			}
		}
	}
}