forked from badaix/snapcast
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclientConnection.h
136 lines (104 loc) · 3.61 KB
/
clientConnection.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef CLIENT_CONNECTION_H
#define CLIENT_CONNECTION_H
#include <string>
#include <thread>
#include <atomic>
#include <mutex>
#include <memory>
#include <asio.hpp>
#include <condition_variable>
#include <set>
#include "message/message.h"
#include "common/timeDefs.h"
using asio::ip::tcp;
class ClientConnection;
/// Used to synchronize server requests (wait for server response)
struct PendingRequest
{
PendingRequest(uint16_t reqId) : id(reqId), response(NULL) {};
uint16_t id;
std::shared_ptr<msg::SerializedMessage> response;
std::condition_variable cv;
};
/// would be nicer to use std::exception_ptr
/// but not supported on all plattforms
typedef std::shared_ptr<std::exception> shared_exception_ptr;
/// Interface: callback for a received message and error reporting
class MessageReceiver
{
public:
virtual ~MessageReceiver() = default;
virtual void onMessageReceived(ClientConnection* connection, const msg::BaseMessage& baseMessage, char* buffer) = 0;
virtual void onException(ClientConnection* connection, shared_exception_ptr exception) = 0;
};
/// Endpoint of the server connection
/**
* Server connection endpoint.
* Messages are sent to the server with the "send" method (async).
* Messages are sent sync to server with the sendReq method.
*/
class ClientConnection
{
public:
/// ctor. Received message from the server are passed to MessageReceiver
ClientConnection(MessageReceiver* receiver, const std::string& host, size_t port);
virtual ~ClientConnection();
virtual void start();
virtual void stop();
virtual bool send(const msg::BaseMessage* message) const;
/// Send request to the server and wait for answer
virtual std::shared_ptr<msg::SerializedMessage> sendRequest(const msg::BaseMessage* message, const chronos::msec& timeout = chronos::msec(1000));
/// Send request to the server and wait for answer of type T
template <typename T>
std::shared_ptr<T> sendReq(const msg::BaseMessage* message, const chronos::msec& timeout = chronos::msec(1000))
{
std::shared_ptr<msg::SerializedMessage> reply = sendRequest(message, timeout);
if (!reply)
return NULL;
std::shared_ptr<T> msg(new T);
msg->deserialize(reply->message, reply->buffer);
return msg;
}
std::string getMacAddress() const;
virtual bool active() const
{
return active_;
}
virtual bool connected() const
{
return (socket_ != nullptr);
// return (connected_ && socket);
}
protected:
virtual void reader();
void socketRead(void* to, size_t bytes);
void getNextMessage();
asio::io_service io_service_;
mutable std::mutex socketMutex_;
std::shared_ptr<tcp::socket> socket_;
std::atomic<bool> active_;
std::atomic<bool> connected_;
MessageReceiver* messageReceiver_;
mutable std::mutex pendingRequestsMutex_;
std::set<std::shared_ptr<PendingRequest>> pendingRequests_;
uint16_t reqId_;
std::string host_;
size_t port_;
std::thread* readerThread_;
chronos::msec sumTimeout_;
};
#endif