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