kike: stubplement CAP
This commit is contained in:
		
							parent
							
								
									55fde4803c
								
							
						
					
					
						commit
						20fc6c17d1
					
				| @ -48,6 +48,7 @@ | ||||
| 403 IRC_ERR_NOSUCHCHANNEL "%s :No such channel" | ||||
| 404 IRC_ERR_CANNOTSENDTOCHAN "%s :Cannot send to channel" | ||||
| 409 IRC_ERR_NOORIGIN ":No origin specified" | ||||
| 410 IRC_ERR_INVALIDCAPCMD "%s :%s" | ||||
| 411 IRC_ERR_NORECIPIENT ":No recipient given (%s)" | ||||
| 412 IRC_ERR_NOTEXTTOSEND ":No text to send" | ||||
| 421 IRC_ERR_UNKNOWNCOMMAND "%s: Unknown command" | ||||
|  | ||||
							
								
								
									
										67
									
								
								kike.c
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								kike.c
									
									
									
									
									
								
							| @ -308,10 +308,13 @@ struct client | ||||
| 	struct poller_timer kill_timer;     ///< Hard kill timeout
 | ||||
| 
 | ||||
| 	bool initialized;                   ///< Has any data been received yet?
 | ||||
| 	bool cap_negotiating;               ///< Negotiating capabilities
 | ||||
| 	bool registered;                    ///< The user has registered
 | ||||
| 	bool closing_link;                  ///< Closing link
 | ||||
| 	bool half_closed;                   ///< Closing link: conn. is half-closed
 | ||||
| 
 | ||||
| 	unsigned long cap_version;          ///< CAP protocol version
 | ||||
| 
 | ||||
| 	bool ssl_rx_want_tx;                ///< SSL_read() wants to write
 | ||||
| 	bool ssl_tx_want_rx;                ///< SSL_write() wants to read
 | ||||
| 	SSL *ssl;                           ///< SSL connection
 | ||||
| @ -339,6 +342,7 @@ client_init (struct client *self) | ||||
| 	self->socket_fd = -1; | ||||
| 	str_init (&self->read_buffer); | ||||
| 	str_init (&self->write_buffer); | ||||
| 	self->cap_version = 301; | ||||
| 	// TODO: make this configurable and more fine-grained
 | ||||
| 	flood_detector_init (&self->antiflood, 10, 20); | ||||
| 	str_map_init (&self->invites); | ||||
| @ -1078,6 +1082,8 @@ irc_try_finish_registration (struct client *c) | ||||
| 	struct server_context *ctx = c->ctx; | ||||
| 	if (!c->nickname || !c->username || !c->realname) | ||||
| 		return; | ||||
| 	if (c->registered || c->cap_negotiating) | ||||
| 		return; | ||||
| 
 | ||||
| 	c->registered = true; | ||||
| 	irc_send_reply (c, IRC_RPL_WELCOME, c->nickname, c->username, c->hostname); | ||||
| @ -1109,6 +1115,66 @@ irc_try_finish_registration (struct client *c) | ||||
| 			ctx->server_name, c->nickname, c->ssl_cert_fingerprint); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| irc_handle_cap (const struct irc_message *msg, struct client *c) | ||||
| { | ||||
| 	if (msg->params.len < 1) | ||||
| 		RETURN_WITH_REPLY (c, IRC_ERR_NEEDMOREPARAMS, msg->command); | ||||
| 
 | ||||
| 	struct str_vector v; | ||||
| 	str_vector_init (&v); | ||||
| 
 | ||||
| 	const char *subcommand = msg->params.vector[0]; | ||||
| 	const char *params = ""; | ||||
| 	if (msg->params.len > 1) | ||||
| 	{ | ||||
| 		params = msg->params.vector[1]; | ||||
| 		split_str_ignore_empty (params, ' ', &v); | ||||
| 	} | ||||
| 
 | ||||
| 	const char *target = c->nickname ? c->nickname : "*"; | ||||
| 	if (!irc_strcmp (subcommand, "LS")) | ||||
| 	{ | ||||
| 		if (v.len == 1 && !xstrtoul (&c->cap_version, v.vector[0], 10)) | ||||
| 			irc_send_reply (c, IRC_ERR_INVALIDCAPCMD, | ||||
| 				subcommand, "Ignoring invalid protocol version number"); | ||||
| 
 | ||||
| 		c->cap_negotiating = true; | ||||
| 		// TODO: actually implement a few capabilities
 | ||||
| 		client_send (c, "CAP %s LS :", target); | ||||
| 	} | ||||
| 	else if (!irc_strcmp (subcommand, "LIST")) | ||||
| 	{ | ||||
| 		// TODO: list currently enabled capabilities
 | ||||
| 		client_send (c, "CAP %s LIST :", target); | ||||
| 	} | ||||
| 	else if (!irc_strcmp (subcommand, "REQ")) | ||||
| 	{ | ||||
| 		c->cap_negotiating = true; | ||||
| 		// TODO: process the capability change request, "-" disables
 | ||||
| 		if (v.len) | ||||
| 			client_send (c, "CAP %s NAK :%s", target, params); | ||||
| 		else | ||||
| 			client_send (c, "CAP %s ACK :%s", target, params); | ||||
| 	} | ||||
| 	else if (!irc_strcmp (subcommand, "ACK")) | ||||
| 	{ | ||||
| 		if (v.len) | ||||
| 			irc_send_reply (c, IRC_ERR_INVALIDCAPCMD, | ||||
| 				subcommand, "No acknowledgable capabilities supported"); | ||||
| 	} | ||||
| 	else if (!irc_strcmp (subcommand, "END")) | ||||
| 	{ | ||||
| 		c->cap_negotiating = false; | ||||
| 		irc_try_finish_registration (c); | ||||
| 	} | ||||
| 	else | ||||
| 		irc_send_reply (c, IRC_ERR_INVALIDCAPCMD, | ||||
| 			subcommand, "Invalid CAP subcommand"); | ||||
| 
 | ||||
| 	str_vector_free (&v); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| irc_handle_pass (const struct irc_message *msg, struct client *c) | ||||
| { | ||||
| @ -2516,6 +2582,7 @@ irc_register_handlers (struct server_context *ctx) | ||||
| 	// TODO: add a field for oper-only commands?
 | ||||
| 	static const struct irc_command message_handlers[] = | ||||
| 	{ | ||||
| 		{ "CAP",      false, irc_handle_cap      }, | ||||
| 		{ "PASS",     false, irc_handle_pass     }, | ||||
| 		{ "NICK",     false, irc_handle_nick     }, | ||||
| 		{ "USER",     false, irc_handle_user     }, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user