Connection.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. #pragma once
  2. #include "../global.h"
  3. #include <string>
  4. #include <vector>
  5. #include <set>
  6. #include <boost/type_traits/is_fundamental.hpp>
  7. #include <boost/type_traits/is_enum.hpp>
  8. #include <boost/mpl/eval_if.hpp>
  9. #include <boost/mpl/equal_to.hpp>
  10. #include <boost/mpl/int.hpp>
  11. #include <boost/mpl/identity.hpp>
  12. #include <boost/thread.hpp>
  13. const int version = 63;
  14. class CConnection;
  15. namespace mpl = boost::mpl;
  16. namespace boost
  17. {
  18. namespace asio
  19. {
  20. namespace ip
  21. {
  22. class tcp;
  23. }
  24. class io_service;
  25. template <typename Protocol> class stream_socket_service;
  26. template <typename Protocol,typename StreamSocketService>
  27. class basic_stream_socket;
  28. template <typename Protocol> class socket_acceptor_service;
  29. template <typename Protocol,typename SocketAcceptorService>
  30. class basic_socket_acceptor;
  31. }
  32. class mutex;
  33. };
  34. enum SerializationLvl
  35. {
  36. Wrong=0,
  37. Primitive,
  38. Serializable
  39. };
  40. template<typename T>
  41. struct SerializationLevel
  42. {
  43. typedef mpl::integral_c_tag tag;
  44. typedef
  45. typename mpl::eval_if<
  46. boost::is_fundamental<T>,
  47. mpl::int_<Primitive>,
  48. //else
  49. typename mpl::eval_if<
  50. boost::is_class<T>,
  51. mpl::int_<Serializable>,
  52. //else
  53. typename mpl::eval_if<
  54. boost::is_array<T>,
  55. mpl::int_<Primitive>,
  56. //else
  57. typename mpl::eval_if<
  58. boost::is_enum<T>,
  59. mpl::int_<Primitive>,
  60. //else
  61. mpl::int_<Wrong>
  62. >
  63. >
  64. >
  65. >::type type;
  66. static const int value = SerializationLevel::type::value;
  67. };
  68. template <typename Serializer> class DLL_EXPORT COSer
  69. {
  70. public:
  71. COSer(){};
  72. Serializer * This()
  73. {
  74. return static_cast<Serializer*>(this);
  75. }
  76. template<class T>
  77. Serializer & operator<<(const T &t)
  78. {
  79. this->This()->save(t);
  80. return * this->This();
  81. }
  82. template<class T>
  83. COSer & operator&(T & t){
  84. return * this->This() << t;
  85. }
  86. };
  87. template <typename Serializer> class DLL_EXPORT CISer
  88. {
  89. public:
  90. CISer(){};
  91. Serializer * This()
  92. {
  93. return static_cast<Serializer*>(this);
  94. }
  95. template<class T>
  96. Serializer & operator>>(T &t)
  97. {
  98. this->This()->load(t);
  99. return * this->This();
  100. }
  101. template<class T>
  102. CISer & operator&(T & t){
  103. return * this->This() >> t;
  104. }
  105. };
  106. template<typename Ser,typename T>
  107. struct SavePrimitive
  108. {
  109. static void invoke(Ser &s, const T &data)
  110. {
  111. s.savePrimitive(data);
  112. }
  113. };
  114. template<typename Ser,typename T>
  115. struct SaveSerializable
  116. {
  117. static void invoke(Ser &s, const T &data)
  118. {
  119. s.saveSerializable(data);
  120. }
  121. };
  122. template<typename Ser,typename T>
  123. struct LoadPrimitive
  124. {
  125. static void invoke(Ser &s, T &data)
  126. {
  127. s.loadPrimitive(data);
  128. }
  129. };
  130. template<typename Ser,typename T>
  131. struct LoadSerializable
  132. {
  133. static void invoke(Ser &s, T &data)
  134. {
  135. s.loadSerializable(data);
  136. }
  137. };
  138. template<typename Ser,typename T>
  139. struct SaveWrong
  140. {
  141. static void invoke(Ser &s, const T &data)
  142. {
  143. throw std::exception("Wrong save serialization call!");
  144. }
  145. };
  146. template<typename Ser,typename T>
  147. struct LoadWrong
  148. {
  149. static void invoke(Ser &s, const T &data)
  150. {
  151. throw std::exception("Wrong load serialization call!");
  152. }
  153. };
  154. class DLL_EXPORT CConnection
  155. :public CISer<CConnection>, public COSer<CConnection>
  156. {
  157. std::ostream &out;
  158. CConnection(void);
  159. void init();
  160. public:
  161. boost::mutex *rmx, *wmx; // read/write mutexes
  162. template <typename T>
  163. void savePrimitive(const T &data)
  164. {
  165. write(&data,sizeof(data));
  166. }
  167. template <typename T>
  168. void loadPrimitive(T &data)
  169. {
  170. read(&data,sizeof(data));
  171. }
  172. template <typename T>
  173. void saveSerializable(const T &data)
  174. {
  175. const_cast<T&>(data).serialize(*static_cast<COSer<CConnection>*>(this),version);
  176. }
  177. template <typename T>
  178. void loadSerializable(T &data)
  179. {
  180. data.serialize(*static_cast<CISer<CConnection>*>(this),version);
  181. }
  182. template <typename T>
  183. void saveSerializable(const std::vector<T> &data)
  184. {
  185. boost::uint32_t length = data.size();
  186. *this << length;
  187. for(ui32 i=0;i<length;i++)
  188. *this << data[i];
  189. }
  190. template <typename T>
  191. void loadSerializable(std::vector<T> &data)
  192. {
  193. boost::uint32_t length;
  194. *this >> length;
  195. data.resize(length);
  196. for(ui32 i=0;i<length;i++)
  197. *this >> data[i];
  198. }
  199. template <typename T>
  200. void saveSerializable(const std::set<T> &data)
  201. {
  202. std::set<T> &d = const_cast<std::set<T> &>(data);
  203. boost::uint32_t length = d.size();
  204. *this << length;
  205. for(typename std::set<T>::iterator i=d.begin();i!=d.end();i++)
  206. *this << *i;
  207. }
  208. template <typename T>
  209. void loadSerializable(std::set<T> &data)
  210. {
  211. boost::uint32_t length;
  212. *this >> length;
  213. T ins;
  214. for(ui32 i=0;i<length;i++)
  215. {
  216. *this >> ins;
  217. data.insert(ins);
  218. }
  219. }
  220. template <typename T1, typename T2>
  221. void saveSerializable(const std::pair<T1,T2> &data)
  222. {
  223. *this << data.first << data.second;
  224. }
  225. template <typename T1, typename T2>
  226. void loadSerializable(std::pair<T1,T2> &data)
  227. {
  228. *this >> data.first >> data.second;
  229. }
  230. template <typename T1, typename T2>
  231. void saveSerializable(const std::map<T1,T2> &data)
  232. {
  233. *this << ui32(data.size());
  234. for(typename std::map<T1,T2>::const_iterator i=data.begin();i!=data.end();i++)
  235. *this << i->first << i->second;
  236. }
  237. template <typename T1, typename T2>
  238. void loadSerializable(std::map<T1,T2> &data)
  239. {
  240. ui32 length;
  241. *this >> length;
  242. T1 t;
  243. for(int i=0;i<length;i++)
  244. {
  245. *this >> t;
  246. *this >> data[t];
  247. }
  248. }
  249. template <typename T>
  250. void save(const T &data)
  251. {
  252. typedef
  253. //if
  254. typename mpl::eval_if< mpl::equal_to<SerializationLevel<T>,mpl::int_<Primitive> >,
  255. mpl::identity<SavePrimitive<CConnection,T> >,
  256. //else if
  257. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Serializable> >,
  258. mpl::identity<SaveSerializable<CConnection,T> >,
  259. //else
  260. mpl::identity<SaveWrong<CConnection,T> >
  261. >
  262. >::type typex;
  263. typex::invoke(*this, data);
  264. }
  265. template <typename T>
  266. void load(T &data)
  267. {
  268. typedef
  269. //if
  270. typename mpl::eval_if< mpl::equal_to<SerializationLevel<T>,mpl::int_<Primitive> >,
  271. mpl::identity<LoadPrimitive<CConnection,T> >,
  272. //else if
  273. typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Serializable> >,
  274. mpl::identity<LoadSerializable<CConnection,T> >,
  275. //else
  276. mpl::identity<LoadWrong<CConnection,T> >
  277. >
  278. >::type typex;
  279. typex::invoke(*this, data);
  280. }
  281. boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > * socket;
  282. bool logging;
  283. bool connected;
  284. bool myEndianess, contactEndianess; //true if little endian, if ednianess is different we'll have to revert recieved multi-byte vars
  285. boost::asio::io_service *io_service;
  286. std::string name; //who uses this connection
  287. CConnection
  288. (std::string host, std::string port, std::string Name, std::ostream & Out);
  289. CConnection
  290. (boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > * acceptor,
  291. boost::asio::io_service *Io_service, std::string Name, std::ostream & Out);
  292. CConnection
  293. (boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > * Socket,
  294. std::string Name, std::ostream & Out); //use immediately after accepting connection into socket
  295. int write(const void * data, unsigned size);
  296. int read(void * data, unsigned size);
  297. int readLine(void * data, unsigned maxSize);
  298. ~CConnection(void);
  299. };
  300. template<>
  301. void CConnection::saveSerializable<std::string>(const std::string &data);
  302. template <>
  303. void CConnection::loadSerializable<std::string>(std::string &data);