DaZeus  2.0
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Friends Macros
plugincomm.h
Go to the documentation of this file.
1 
6 #ifndef SOCKETPLUGIN_H
7 #define SOCKETPLUGIN_H
8 
9 #include <sstream>
10 #include <utility>
11 #include <map>
12 #include <jansson.h>
13 #include <unistd.h>
14 #include <assert.h>
15 #include <stdio.h>
16 #include "utils.h"
17 #include "../contrib/libdazeus-irc/src/utils.h"
18 #include "network.h"
19 
20 namespace dazeus {
21 
22 class Database;
23 class ConfigReader;
24 class DaZeus;
25 
27 {
28 
29  struct Command {
30  Network &network;
31  std::string origin;
32  std::string channel;
33  std::string command;
34  std::string fullArgs;
35  std::vector<std::string> args;
36  bool whoisSent;
37  Command(Network &n) : network(n), origin(), channel(),
38  command(), fullArgs(), args(), whoisSent(false) {}
39  };
40 
41  struct RequirementInfo {
42  bool needsNetwork;
43  bool needsReceiver;
44  bool needsSender;
45  Network *wantedNetwork;
46  std::string wantedReceiver;
47  std::string wantedSender;
48  // Constructor which allows anything
49  RequirementInfo() : needsNetwork(false), needsReceiver(false),
50  needsSender(false), wantedNetwork(0), wantedReceiver(),
51  wantedSender() {}
52  // Constructor which allows anything on a network
53  RequirementInfo(Network *n) : needsNetwork(true), needsReceiver(false),
54  needsSender(false), wantedNetwork(n), wantedReceiver(),
55  wantedSender() {}
56  // Constructor which allows anything from a sender (isSender=true)
57  // or to some receiver (isSender=false)
58  RequirementInfo(Network *n, std::string obj, bool isSender) :
59  needsNetwork(true), needsReceiver(false),
60  needsSender(false), wantedNetwork(n), wantedReceiver(),
61  wantedSender()
62  {
63  if(isSender) {
64  needsSender = true; wantedSender = obj;
65  } else {
66  needsReceiver = true; wantedReceiver = obj;
67  }
68  }
69  private:
70  // explicitly disable copy constructor
71  RequirementInfo(const RequirementInfo&);
72  void operator=(const RequirementInfo&);
73  };
74 
75  struct SocketInfo {
76  public:
77  SocketInfo(std::string t = std::string()) : type(t),
78  subscriptions(), commands(), waitingSize(0), readahead(),
79  protocol_version(0) {}
80  bool isSubscribed(std::string t) const {
81  return contains(subscriptions, strToUpper(t));
82  }
83  bool unsubscribe(std::string t) {
84  if(!isSubscribed(t)) return false;
85  erase(subscriptions, strToUpper(t));
86  return true;
87  }
88  bool subscribe(std::string t) {
89  if(isSubscribed(t))
90  return false;
91  subscriptions.push_back(strToUpper(t));
92  return true;
93  }
94  bool isSubscribedToCommand(const std::string &cmd, const std::string &recv,
95  const std::string &sender, bool identified, const Network &network)
96  {
97  std::multimap<std::string,RequirementInfo*>::iterator it;
98  for(it = commands.begin(); it != commands.end(); ++it) {
99  if(it->first != cmd) {
100  continue;
101  } else if(it->second->needsNetwork && it->second->wantedNetwork != &network) {
102  continue;
103  } else if(it->second->needsReceiver && it->second->wantedReceiver != recv) {
104  continue;
105  } else if(it->second->needsSender) {
106  if(!identified || it->second->wantedSender != sender)
107  continue;
108  }
109  return true;
110  }
111  return false;
112  }
113  bool commandMightNeedWhois(const std::string &cmd) {
114  std::multimap<std::string,RequirementInfo*>::iterator it;
115  for(it = commands.begin(); it != commands.end(); ++it) {
116  if(it->first != cmd) {
117  continue;
118  } else if(it->second->needsSender) {
119  return true;
120  }
121  }
122  return false;
123  }
124  void subscribeToCommand(const std::string &cmd, RequirementInfo *info) {
125  commands.insert(std::make_pair(cmd, info));
126  }
127  void dispatch(int d, std::string event, std::vector<std::string> parameters) {
128  assert(!contains(event, ' '));
129 
130  json_t *params = json_array();
131  std::vector<std::string>::iterator it;
132  for(it = parameters.begin(); it != parameters.end(); ++it) {
133  json_array_append_new(params, json_string(it->c_str()));
134  }
135 
136  json_t *n = json_object();
137  json_object_set_new(n, "event", json_string(event.c_str()));
138  json_object_set_new(n, "params", params);
139 
140  char *json_raw = json_dumps(n, 0);
141  std::string jsonMsg = json_raw;
142  free(json_raw);
143  std::stringstream mstr;
144  mstr << jsonMsg.length();
145  mstr << jsonMsg;
146  mstr << "\n";
147  std::string final_message = mstr.str();
148  if(write(d, final_message.c_str(), final_message.length()) != (unsigned)final_message.length()) {
149  fprintf(stderr, "Failed to write correct number of JSON bytes to client socket in dispatch().\n");
150  close(d);
151  }
152  json_decref(n);
153  }
154  bool didHandshake() {
155  return protocol_version != 0;
156  }
157  std::string type;
158  std::vector<std::string> subscriptions;
159  std::multimap<std::string,RequirementInfo*> commands;
160  int waitingSize;
161  std::string readahead;
162  std::string plugin_name;
163  std::string plugin_version;
164  int protocol_version;
165  std::string config_group;
166  };
167 
168  public:
169  PluginComm( Database *d, ConfigReader *c, DaZeus *bot );
170  virtual ~PluginComm();
171  void dispatch(const std::string &event, const std::vector<std::string> &parameters);
172  void init();
173  void ircEvent(const std::string &event, const std::string &origin,
174  const std::vector<std::string> &params, Network *n );
175  void run(int timeout);
176 
177  private:
178  // explicitly disable copy constructor
179  PluginComm(const PluginComm&);
180  void operator=(const PluginComm&);
181 
182  void newTcpConnection();
183  void newLocalConnection();
184  void poll();
185  void messageReceived(const std::string &origin, const std::string &message, const std::string &receiver, Network *n);
186 
187  std::vector<int> tcpServers_;
188  std::vector<int> localServers_;
189  std::vector<Command*> commandQueue_;
190  std::map<int,SocketInfo> sockets_;
191  Database *database_;
192  ConfigReader *config_;
193  DaZeus *dazeus_;
194  void handle(int dev, const std::string &line, SocketInfo &info);
195  void flushCommandQueue(const std::string &nick = std::string(), bool identified = false);
196 };
197 
198 }
199 
200 #endif