The Battle for Wesnoth  1.15.0+dev
playturn_network_adapter.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017-2018 by the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
15 #include "log.hpp"
16 
17 #include "utils/functional.hpp"
18 #include <iostream>
19 #include <cassert>
20 
21 
22 static lg::log_domain log_network("network");
23 #define LOG_NW LOG_STREAM(info, log_network)
24 #define ERR_NW LOG_STREAM(err, log_network)
25 
27 {
28  assert(!data_.empty());
29 
30  this->data_.emplace_back();
31  config& back = data_.back();
32  bool has_data = false;
33  try
34  {
35  has_data = this->network_reader_(back);
36  }
37  catch(...)
38  {
39  //Readin from network can throw, we want to ignore the possibly corrupt packet in this case.
40  this->data_.pop_back();
41  throw;
42  }
43  //ping is handeled by network.cpp and we can ignore it.
44  back.remove_attribute("ping");
45  if((!has_data) || back.empty())
46  {
47  this->data_.pop_back();
48  return;
49  }
50  assert(!data_.back().empty());
51 
52  if(!back.attribute_range().empty() )
53  {
54  ERR_NW << "found unexpected attribute:" <<back.debug() << std::endl;
55  this->data_.pop_back();
56  //ignore those here
57  }
58  assert(!data_.back().empty());
59  //there should be no attributes left.
60 }
61 
63 {
64  assert(!data_.empty());
65  if (data_.size() > 1) return false;
66  return this->next_ == data_.back().ordered_end();
67 }
68 
70 {
71  data_front_.emplace_front(std::move(cfg));
72 }
73 
75 {
76  assert(dst.empty());
77  if(!data_front_.empty())
78  {
79  dst = std::move(data_front_.back());
80  data_front_.pop_back();
81  return true;
82  }
83  if(is_at_end())
84  {
86  }
87  if(is_at_end())
88  {
89  //that means we couldn't read anything from the network.
90  return false;
91  }
92  //skip empty data.
93  while(next_ == data_.begin()->ordered_end())
94  {
95  data_.pop_front();
96  next_ = data_.front().ordered_begin();
97  assert(!is_at_end());
98  }
99  config& child = dst.add_child(next_->key);
100  config& child_old = next_->cfg;
101  if(next_->key == "turn")
102  {
103  //split [turn] indo different [turn] for each child.
104  assert(next_->cfg.all_children_count() > next_command_num_);
105  config::all_children_iterator itor = child_old.ordered_begin();
106  std::advance(itor, next_command_num_);
107  config& childchild_old = itor->cfg;
108  config& childchild = child.add_child(itor->key);
109  childchild.swap(childchild_old);
110 
112  if(next_->cfg.all_children_count() == next_command_num_)
113  {
114  next_command_num_ = 0;
115  ++next_;
116  }
117  return true;
118  }
119  else
120  {
121  child.swap(child_old);
122  ++next_;
123  return true;
124  }
125 }
126 
128  : network_reader_(source)
129  , data_({config()})
130  , data_front_()
131  , next_(data_.front().ordered_end())
132  , next_command_num_(0)
133 
134 {
135 
136 }
137 
138 
140 {
141  try {
142  if(!is_at_end())
143  {
144  LOG_NW << "Destroying playturn_network_adapter with an non empty buffer, this means loss of network data" << std::endl;
145  }
146  } catch (...) {}
147 }
148 
150 {
151  network_reader_ = source;
152 }
153 
154 
155 static bool read_config(config& src, config& dst)
156 {
157  assert(dst.empty());
158  if(!src.empty())
159  {
160  src.swap(dst);
161  return true;
162  }
163  else
164  {
165  return false;
166  }
167 }
168 
170 {
171  return std::bind(read_config, std::ref(cfg), _1);
172 }
#define ERR_NW
void remove_attribute(config_key_type key)
Definition: config.cpp:235
void set_source(source_type source)
const_attr_itors attribute_range() const
Definition: config.cpp:809
#define LOG_NW
void swap(config &cfg)
Definition: config.cpp:1377
static lg::log_domain log_network("network")
config::all_children_iterator next_
std::function< bool(config &)> source_type
static source_type get_source_from_config(config &src)
config & add_child(config_key_type key)
Definition: config.cpp:476
const_all_children_iterator ordered_begin() const
Definition: config.cpp:901
Standard logging facilities (interface).
static bool read_config(config &src, config &dst)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
bool empty() const
Definition: config.cpp:884
std::string debug() const
Definition: config.cpp:1277
playturn_network_adapter(source_type source)