Example #1
0
func handle_api_or_parent_connection(conn *net.TCPConn) {
	defer conn.Close() // Connection should be closed, after return this function
	var (
		err            tree_lib.TreeError
		msg_data       []byte
		info_data      []byte
		conn_name      string
		is_api         = false
		conn_node_info node_info.NodeInfo
		api_val        *big.Int
	)
	err.From = tree_lib.FROM_HANDLE_API_OR_PARENT_CONNECTION
	// Making basic handshake to check the API validation
	// Connected Parent receiving name of the child(current node) and checking is it valid or not
	// if it is valid name then parent sending his name as an answer
	// otherwise it sending CLOSE_CONNECTION_MARK and closing connection

	info_data, err.Err = ffjson.Marshal(node_info.CurrentNodeInfo)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	_, err.Err = tree_lib.SendMessage(info_data, conn)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	info_data, err = tree_lib.ReadMessage(conn)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	conn_name = string(info_data)
	if conn_name == CLOSE_CONNECTION_MARK {
		tree_log.Info(err.From, "Connection closed by parent node. Bad tree network handshake ! ", "Parent Addr: ", conn.RemoteAddr().String())
		return
	}

	err.Err = ffjson.Unmarshal(info_data, &conn_node_info)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	if strings.Contains(conn_node_info.Name, tree_api.API_NAME_PREFIX) {
		api_val = big.NewInt(conn_node_info.Value)
		api_connections[api_val] = conn
		is_api = true
	} else {
		// TODO: Think about conn_node_info if we need to more checking for parent node info
		parentConnection = conn
	}

	if is_api {
		tree_event.TriggerWithData(tree_event.ON_API_CONNECTED, info_data)
	} else {
		tree_event.TriggerWithData(tree_event.ON_PARENT_CONNECTED, info_data)
	}

	// Listening parent messages
	for {
		msg_data, err = tree_lib.ReadMessage(conn)
		if !err.IsNull() {
			tree_log.Error(err.From, " reading data from -> ", conn_name, " ", err.Error())
			break
		}

		// Handling message events
		handle_message(is_api, true, msg_data)
	}

	if is_api {
		api_connections[api_val] = nil
		delete(api_connections, api_val)
		tree_event.TriggerWithData(tree_event.ON_API_DISCONNECTED, info_data)
	} else {
		parentConnection = nil
		tree_event.TriggerWithData(tree_event.ON_PARENT_DISCONNECTED, info_data)
	}
}
Example #2
0
func ChildConnect(name string) (err tree_lib.TreeError) {
	var (
		conn           *net.TCPConn
		curr_data      []byte
		ch_info_data   []byte
		conn_node_info node_info.NodeInfo
		msg            []byte
	)
	err.From = tree_lib.FROM_CHILD_CONNECT
	conn, err = TcpConnect(node_info.ChildsNodeInfo[name].TreeIp, node_info.ChildsNodeInfo[name].TreePort)
	if !err.IsNull() {
		tree_log.Error(err.From, " child_connect -> ", name, " ", err.Error())
		return
	}
	defer conn.Close()

	ch_info_data, err = tree_lib.ReadMessage(conn)
	if !err.IsNull() {
		tree_log.Error(err.From, " child handshake -> ", name, " ", err.Error())
		return
	}

	err.Err = ffjson.Unmarshal(ch_info_data, &conn_node_info)
	if !err.IsNull() {
		tree_log.Error(err.From, " child handshake -> ", name, " ", err.Error())
		return
	}

	// If name revieved from connection not same name as we have
	// Then we connected to wrong server, just returning
	// defer will close connection
	if conn_node_info.Name != name {
		tree_lib.SendMessage([]byte(CLOSE_CONNECTION_MARK), conn)
		return
	}

	curr_data, err.Err = ffjson.Marshal(node_info.CurrentNodeInfo)
	if !err.IsNull() {
		tree_log.Error(err.From, " child handshake -> ", name, " ", err.Error())
		return
	}

	_, err.Err = tree_lib.SendMessage(curr_data, conn)
	if !err.IsNull() {
		tree_log.Error(err.From, " child handshake sending current info to -> ", name, " ", err.Error())
		return
	}

	child_connections[name] = conn

	tree_event.TriggerWithData(tree_event.ON_CHILD_CONNECTED, ch_info_data)

	for {
		msg, err = tree_lib.ReadMessage(conn)
		if !err.IsNull() {
			tree_log.Error(err.From, " reading data from child -> ", name, " ", err.Error())
			break
		}

		handle_message(false, false, msg)
	}

	child_connections[name] = nil
	delete(child_connections, name)

	tree_event.TriggerWithData(tree_event.ON_CHILD_DISCONNECTED, ch_info_data)

	return
}