Implement client-server feature negotiation.
[paraslash.git] / command.c
index f520e3e..cdc42fa 100644 (file)
--- a/command.c
+++ b/command.c
@@ -701,6 +701,46 @@ static void reset_signals(void)
        para_sigaction(SIGHUP, SIG_DFL);
 }
 
+static int parse_auth_request(char *buf, int len, struct user **u,
+               bool *use_sideband)
+{
+       int ret;
+       char *p, *username, **features = NULL;
+       size_t auth_rq_len = strlen(AUTH_REQUEST_MSG);
+
+       *u = NULL;
+       *use_sideband = false;
+       if (len < auth_rq_len + 2)
+               return -E_AUTH_REQUEST;
+       if (strncmp(buf, AUTH_REQUEST_MSG, auth_rq_len) != 0)
+               return -E_AUTH_REQUEST;
+       username = buf + auth_rq_len;
+       p = strchr(username, ' ');
+       if (p) {
+               int i;
+               if (p == username)
+                       return -E_AUTH_REQUEST;
+               *p = '\0';
+               p++;
+               create_argv(p, ",", &features);
+               for (i = 0; features[i]; i++) {
+                       if (strcmp(features[i], "sideband") == 0)
+                               *use_sideband = true;
+                       else {
+                               ret = -E_BAD_FEATURE;
+                               goto out;
+                       }
+               }
+       }
+       PARA_DEBUG_LOG("received auth request for user %s (sideband = %s)\n",
+               username, *use_sideband? "true" : "false");
+       *u = lookup_user(username);
+       ret = 1;
+out:
+       free_argv(features);
+       return ret;
+}
+
 /**
  * Perform user authentication and execute a command.
  *
@@ -746,19 +786,17 @@ __noreturn void handle_connect(int fd, const char *peername)
                goto net_err;
        /* send Welcome message */
        ret = write_va_buffer(fd, "This is para_server, version "
-               PACKAGE_VERSION  ".\n" );
+               PACKAGE_VERSION  ".\n"
+               "Features: sideband,foo\n"
+       );
        if (ret < 0)
                goto net_err;
        /* recv auth request line */
        ret = recv_buffer(fd, buf, sizeof(buf));
        if (ret < 0)
                goto net_err;
-       if (ret < 10) {
-               ret = -E_AUTH_REQUEST;
-               goto net_err;
-       }
-       ret = -E_AUTH_REQUEST;
-       if (strncmp(buf, AUTH_REQUEST_MSG, strlen(AUTH_REQUEST_MSG)))
+       ret = parse_auth_request(buf, ret, &cc->u, &cc->use_sideband);
+       if (ret < 0)
                goto net_err;
        p = buf + strlen(AUTH_REQUEST_MSG);
        PARA_DEBUG_LOG("received auth request for user %s\n", p);