about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--bounce.h12
-rw-r--r--client.c19
-rw-r--r--state.c23
3 files changed, 46 insertions, 8 deletions
diff --git a/bounce.h b/bounce.h
index 0929da7..fd64a27 100644
--- a/bounce.h
+++ b/bounce.h
@@ -29,6 +29,8 @@
 
 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
 
+bool verbose;
+
 enum { ParamCap = 15 };
 struct Command {
 	const char *origin;
@@ -50,15 +52,10 @@ static inline struct Command parse(char *line) {
 	return cmd;
 }
 
-bool verbose;
-
 void listenConfig(const char *cert, const char *priv);
 size_t listenBind(int fds[], size_t cap, const char *host, const char *port);
 int listenAccept(struct tls **client, int fd);
 
-bool stateReady(void);
-void stateParse(char *line);
-
 int serverConnect(const char *host, const char *port);
 void serverLogin(
 	const char *pass, const char *auth,
@@ -74,3 +71,8 @@ struct Client *clientAlloc(struct tls *tls);
 void clientFree(struct Client *client);
 bool clientClose(const struct Client *client);
 void clientRecv(struct Client *client);
+void clientSend(struct Client *client, const char *ptr, size_t len);
+
+bool stateReady(void);
+void stateParse(char *line);
+void stateSync(struct Client *client);
diff --git a/client.c b/client.c
index 74d1e5c..442ed2d 100644
--- a/client.c
+++ b/client.c
@@ -63,7 +63,7 @@ bool clientClose(const struct Client *client) {
 	return client->close;
 }
 
-static void clientSend(struct Client *client, const char *ptr, size_t len) {
+void clientSend(struct Client *client, const char *ptr, size_t len) {
 	if (verbose) fprintf(stderr, "\x1B[34m%.*s\x1B[m", (int)len, ptr);
 	while (len) {
 		ssize_t ret = tls_write(client->tls, ptr, len);
@@ -89,25 +89,38 @@ static void format(struct Client *client, const char *format, ...) {
 	clientSend(client, buf, len);
 }
 
+static void passRequired(struct Client *client) {
+	format(
+		client,
+		":invalid 464 * :Password incorrect\r\n"
+		"ERROR :Password incorrect\r\n"
+	);
+	client->close = true;
+}
+
 typedef void Handler(struct Client *client, struct Command cmd);
 
 static void handleNick(struct Client *client, struct Command cmd) {
 	(void)cmd;
 	client->need &= ~NeedNick;
+	if (!client->need) stateSync(client);
+	if (client->need == NeedPass) passRequired(client);
 }
 
 static void handleUser(struct Client *client, struct Command cmd) {
 	(void)cmd;
 	// TODO: Identify client by username.
 	client->need &= ~NeedUser;
+	if (!client->need) stateSync(client);
+	if (client->need == NeedPass) passRequired(client);
 }
 
 static void handlePass(struct Client *client, struct Command cmd) {
 	if (!cmd.params[0] || strcmp(clientPass, cmd.params[0])) {
-		format(client, ":invalid 464 * :Password incorrect\r\n");
-		client->close = true;
+		passRequired(client);
 	} else {
 		client->need &= ~NeedPass;
+		if (!client->need) stateSync(client);
 	}
 }
 
diff --git a/state.c b/state.c
index c7d517e..161fd90 100644
--- a/state.c
+++ b/state.c
@@ -14,8 +14,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <err.h>
 #include <stdbool.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
@@ -128,3 +130,24 @@ void stateParse(char *line) {
 		break;
 	}
 }
+
+void stateSync(struct Client *client) {
+	char buf[4096];
+	int len = snprintf(
+		buf, sizeof(buf),
+		":%s 001 %s :%s\r\n"
+		":%s 002 %s :%s\r\n"
+		":%s 003 %s :%s\r\n"
+		":%s 004 %s %s %s %s %s\r\n",
+		intro.origin, nick, intro.welcome,
+		intro.origin, nick, intro.yourHost,
+		intro.origin, nick, intro.created,
+		intro.origin, nick,
+		intro.myInfo[0], intro.myInfo[1], intro.myInfo[2], intro.myInfo[3]
+	);
+	assert(len > 0 && (size_t)len < sizeof(buf));
+
+	// TODO: Send ISUPPORT.
+
+	clientSend(client, buf, len);
+}