]> git.gir.st - ircpipe.git/blob - spec.txt
use IRCv3 USER command
[ircpipe.git] / spec.txt
1 # ircpipe
2
3 sets up an irc connection, and not much more.
4
5 ## on connection
6
7 - [x] connect
8 - [ ] tls (optional cert validation)
9 - [?] sasl plain (untested)
10 - [x] set user and nick
11 - [ ] if in use, try alternate nick(s)
12 - [ ] if not specified, use random from pattern [a-z0-9]{8}
13 - [ ] wait for motd/001-message
14 - [ ] optionally, do an initial join?
15
16 ## in the background
17
18 - respond to server pings
19 - keep track of when we last received an irc mesasge; if t > $timeout, send ping ourselves.
20 (first implementation can just send a ping every $timeout (milli)seconds)
21 (should $timeout be the time between last message and send-ping or between last message and ping-reponse?)
22 - different timeouts:
23 - ping interval
24 - connect timeout
25 - time between sent message and received response
26 - send/recv block: invalid, due to polling
27
28 ## interfaces
29
30 - read from stdin, write to stdout
31 - cli for setting timeout, user/nick, server info, ...
32 - netcat-like (everything but host[{: }port] optional
33 - how to specify tls?
34 - how to specify auth?
35 - relatively secure password handling!
36
37
38 ## minor TODOs
39
40 - make ping_iv and resp_to configurable
41 - maybe allow HOST:PORT (nc doesn't)
42 - check if port is valid
43 - support ipv6
44 - irc_poll: handle poll() EINTR (don't exit on nonfatal signal received)
45 - handle user EOF
46 - what to do when nick is taken
47 - use random nick
48 - use fallback nick (append '_')
49 - exit
50
51
52 ## future todos:
53 - flood protection!
54 - allow specifying multiple channels to join on startup
55 - allow specifying alternate nicks
56 - failover hosts?
57 - read once before sending NICK and USER
58 (verify this is actually a problem)
59 - port gethostbyname to getaddrinfo
60
61
62 ## dropped features (patches accepted)
63 - nickserv: freenode and hackint support sasl, efenet neither. rest don't care.
64 - sasl cert: don't care for it
65 - optionally use socket instead of stdin/stdout?
66 - checking responses to NICK, JOIN, CAP-REQ, AUTHENTICATE
67 for now, we're just assuming everything went ok.
68 - NICK/USER
69 ok: 001 (checked, to block further commands)
70 err: 432 433 436 437 <nick>
71 - JOIN
72 ok: JOIN <chan>
73 err: 471 473 474 475 403 405 437 <chan>
74 - CAP REQ/CAP END
75 ok: CAP <nick?> ACK
76 err: CAP <nick?> NAK
77 err: 421
78 - AUTHENTICATE
79 ok: 900 903 <nick>
80 err: 902 904 905 908 <nick>
81
82
83 ## for responses
84
85 we need to check and handle multiple responses to commands we've send:
86 - ping: pong (everytime, everywhere. keep current hack)
87 - sasl: cap-ack, 900+903 or 90x (when authenticating, during setup)
88 - (after connecting/authenticating): 001, nick-in-use (everytime, during setup)
89
90 the server may send unrelated responses in-between - including pings - and we
91 want to enforce a timeout in which we expect the response (2000ms).
92
93
94 essentially, we send a command, then block until we receive a response or an error.
95 commands we send that we need to wait for are:
96 - PING
97 ok: PONG :<whatever>
98
99 {{{
100 enum {
101 PONG = 1<<0,
102 CAP_ACK = 1<<1,
103 CAP_NAK = 1<<2,
104 N001 = 1<<3,
105 N900 = 1<<4,
106 N903 = 1<<5,
107 N904 = 1<<6
108 /*...*/
109 };
110 enum { PING, CAP_REQ,
111 int irc_waitfor(const int sockfd, const unsigned int pattern) {
112 // block until one of the specified """patterns""" has been seen (or 2s timeout has been reached).
113 // we need to be able to handle:
114 // - ^PONG( :.+)?
115 // we aren't really interested in the response really
116 // - ^(\d\d\d)
117 // for each command, we want to know which numeric of a limited set was returned
118 // - ^CAP \S* (ACK|NAK)
119 // ack/nak is enough
120 // - maybe other ones in the future
121
122 unsigned int seen = 0;
123
124 while (timer < 2000ms) {
125 if (poll(fds, 1, 2000)) {
126 /* relay whatever we got */
127 n = read(sockfd, buf, BUFSIZ);
128 write(outfd, buf, n);
129
130 /* parse */
131 line = strtok_r(buf, "\n", &saveptr);
132 do {
133 /* skip over prefix (servername): */
134 if (line[0] == ':') while (*line++ != ' ');
135
136 /* match patterns: */
137 if (pattern & PONG) seen |= (strncmp(line, "PONG ", 5) == 0) & PONG;
138 if (pattern & (CAP_ACK|CAP_NAK) && (strncmp(line, "CAP ", 4) == 0)) {
139 seen |= (strstr(line, " ACK :") != NULL) & CAP_ACK;
140 seen |= (strstr(line, " NAK :") != NULL) & CAP_NAK;
141 }
142
143 /* reply to pings: todo */
144 } while (line = strtok_r(NULL, "\n", &saveptr));
145 }
146 }
147
148 return seen;
149 }
150 }}}
Imprint / Impressum