-
Notifications
You must be signed in to change notification settings - Fork 0
/
ident.cpp
130 lines (102 loc) · 3.66 KB
/
ident.cpp
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
#include <sstream>
#include "ident.h"
Ident::Ident(Config irc_config) : config(irc_config) {
// Set up a listen socket.
memset(&address, 0, sizeof (address));
addr_len = sizeof (address);
listen_socket = socket(AF_INET, SOCK_STREAM, 0);
int yes = 1;
if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int)) == -1) {
std::cout << "Ident: Could not reuse socket" << std::endl;
return;
}
listen_event.set<Ident, &Ident::handle_connect > (this);
listen_event.start(listen_socket, ev::READ);
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
// Ident is always on port 113 afaik
int port = 113;
address.sin_port = htons(port);
if (bind(listen_socket, (sockaddr *) & address, sizeof (address)) == -1) {
std::cout << "Ident: Bind failed " << errno << ": " << strerror(errno) << std::endl;
return;
}
if (listen(listen_socket, 1) == -1) {
std::cout << "Ident: Listen failed" << std::endl;
return;
}
// Set socket to non-blocking
int flags = fcntl(listen_socket, F_GETFL);
if (flags == -1) {
std::cout << "Ident: Could not get socket flags" << std::endl;
return;
}
if (fcntl(listen_socket, F_SETFL, flags | O_NONBLOCK) == -1) {
std::cout << "Ident: Could not set non-blocking" << std::endl;
return;
}
// Set up a general timeout for class to live or wait for receive.
timeout_event.set<Ident, &Ident::handle_timeout > (this);
timeout_event.set(config.ident_timeout, 0);
timeout_event.start();
}
Ident::~Ident() {
read_event.stop();
timeout_event.stop();
close(listen_socket);
close(connect_socket);
}
void Ident::handle_connect(ev::io &watcher, int events_flags) {
listen_event.stop();
timeout_event.stop();
connect_socket = accept(listen_socket, (sockaddr *) & address, &addr_len);
if (connect_socket == -1) {
std::cout << "Ident: Accept failed, errno " << errno << ": " << strerror(errno) << std::endl;
delete this;
return;
}
int flags = fcntl(connect_socket, F_GETFL);
if (flags == -1) {
std::cout << "Ident: Could not get connect socket flags" << std::endl;
delete this;
return;
}
if (fcntl(connect_socket, F_SETFL, flags | O_NONBLOCK) == -1) {
std::cout << "Ident: Could not set non-blocking" << std::endl;
delete this;
return;
}
read_event.set<Ident, &Ident::handle_receive > (this);
read_event.start(connect_socket, ev::READ);
timeout_event.start();
}
void Ident::handle_receive(ev::io &watcher, int events_flags) {
read_event.stop();
char buffer[1024 + 1];
memset(buffer, 0, 1024 + 1);
int status = recv(connect_socket, &buffer, 1024, 0);
if (status == -1) {
std::cout << "Ident: incorrect incomming ident" << std::endl;
delete this;
return;
}
std::string line = buffer;
// TODO: better checking
int p = line.find(",");
if (p > 0) {
int first = atoi(line.substr(0, p - 1).c_str());
int last = atoi(line.substr(p + 1).c_str());
std::stringstream identResponse;
identResponse << last << " , " << first << " : USERID : UNIX : " << config.irc_nick_name;
std::string identResponseStr = identResponse.str();
// Send the response string.
send(connect_socket, identResponseStr.c_str(), identResponseStr.size(), MSG_NOSIGNAL);
}
delete this;
}
void Ident::handle_timeout(ev::io &watcher, int eventsFlags) {
timeout_event.stop();
read_event.stop();
std::cout << "Ident: timed out." << std::endl;
delete this;
}