Browse Source

ktp: KTP protocol was changed. If server wants stdout/stdin exchange it must send CMD_ACK with 'incompleted' flag and set features using status

Serj Kalichev 2 years ago
parent
commit
a66e80de87
3 changed files with 51 additions and 5 deletions
  1. 8 2
      klish/ktp.h
  2. 33 1
      klish/ktp/ktp_session.c
  3. 10 2
      klish/ktp/ktpd_session.c

+ 8 - 2
klish/ktp.h

@@ -40,10 +40,16 @@ typedef enum {
 
 
 // Status field. Bitmap
-#define KTP_STATUS_NONE  (uint32_t)0x00000000
-#define KTP_STATUS_ERROR (uint32_t)0x00000001
+typedef enum {
+	KTP_STATUS_NONE = (uint32_t)0x00000000,
+	KTP_STATUS_ERROR = (uint32_t)0x00000001,
+	KTP_STATUS_INCOMPLETED = (uint32_t)0x00000002,
+	KTP_STATUS_INTERACTIVE = (uint32_t)0x00000100,
+} ktp_status_e;
 
 #define KTP_STATUS_IS_ERROR(status) (status & KTP_STATUS_ERROR)
+#define KTP_STATUS_IS_INCOMPLETED(status) (status & KTP_STATUS_INCOMPLETED)
+#define KTP_STATUS_IS_INTERACTIVE(status) (status & KTP_STATUS_INTERACTIVE)
 
 
 #endif // _klish_ktp_h

+ 33 - 1
klish/ktp/ktp_session.c

@@ -39,6 +39,8 @@ struct ktp_session_s {
 	bool_t request_done;
 	int cmd_retcode; // Internal
 	bool_t cmd_retcode_available;
+	ktp_status_e cmd_features;
+	bool_t cmd_features_available;
 };
 
 
@@ -96,6 +98,8 @@ ktp_session_t *ktp_session_new(int sock)
 	ktp->cmd_retcode = -1;
 	ktp->cmd_retcode_available = BOOL_FALSE;
 	ktp->request_done = BOOL_FALSE;
+	ktp->cmd_features = KTP_STATUS_NONE;
+	ktp->cmd_features_available = BOOL_FALSE;
 
 	return ktp;
 }
@@ -136,6 +140,16 @@ bool_t ktp_session_set_done(ktp_session_t *ktp, bool_t done)
 }
 
 
+ktp_status_e ktp_session_cmd_features(const ktp_session_t *ktp)
+{
+	assert(ktp);
+	if (!ktp)
+		return KTP_STATUS_NONE;
+
+	return ktp->cmd_features;
+}
+
+
 faux_error_t *ktp_session_error(const ktp_session_t *ktp)
 {
 	assert(ktp);
@@ -282,6 +296,8 @@ static bool_t ktp_session_process_stdout(ktp_session_t *ktp, const faux_msg_t *m
 
 	if (!ktp->stdout_cb)
 		return BOOL_TRUE; // Just ignore stdout. It's not a bug
+	if (!ktp->cmd_features_available)
+		return BOOL_TRUE; // Drop message
 
 	if (!faux_msg_get_param_by_type(msg, KTP_PARAM_LINE, (void **)&line, &len))
 		return BOOL_TRUE; // It's strange but not a bug
@@ -299,7 +315,9 @@ static bool_t ktp_session_process_stderr(ktp_session_t *ktp, const faux_msg_t *m
 	assert(msg);
 
 	if (!ktp->stderr_cb)
-		return BOOL_TRUE; // Just ignore stdout. It's not a bug
+		return BOOL_TRUE; // Just ignore message. It's not a bug
+	if (!ktp->cmd_features_available)
+		return BOOL_TRUE; // Drop message
 
 	if (!faux_msg_get_param_by_type(msg, KTP_PARAM_LINE,
 			(void **)&line, &len))
@@ -312,10 +330,22 @@ static bool_t ktp_session_process_stderr(ktp_session_t *ktp, const faux_msg_t *m
 static bool_t ktp_session_process_cmd_ack(ktp_session_t *ktp, const faux_msg_t *msg)
 {
 	uint8_t *retcode8bit = NULL;
+	ktp_status_e status = KTP_STATUS_NONE;
 
 	assert(ktp);
 	assert(msg);
 
+	status = faux_msg_get_status(msg);
+	// cmd_ack with flag 'incompleted'
+	if (KTP_STATUS_IS_INCOMPLETED(status)) {
+		// Only first 'incompleted' cmd ack sets cmd features
+		if (!ktp->cmd_features_available) {
+			ktp->cmd_features_available = BOOL_TRUE;
+			ktp->cmd_features = status & KTP_STATUS_INTERACTIVE;
+		}
+		return BOOL_TRUE;
+	}
+
 	if (faux_msg_get_param_by_type(msg, KTP_PARAM_RETCODE,
 		(void **)&retcode8bit, NULL))
 		ktp->cmd_retcode = (int)(*retcode8bit);
@@ -444,6 +474,8 @@ bool_t ktp_session_req_cmd(ktp_session_t *ktp, const char *line,
 	ktp->cmd_retcode = -1;
 	ktp->cmd_retcode_available = BOOL_FALSE;
 	ktp->request_done = BOOL_FALSE; // Be pessimistic
+	ktp->cmd_features = KTP_STATUS_NONE;
+	ktp->cmd_features_available = BOOL_FALSE;
 
 	faux_eloop_loop(ktp->eloop);
 

+ 10 - 2
klish/ktp/ktpd_session.c

@@ -109,7 +109,6 @@ void ktpd_session_free(ktpd_session_t *ktpd)
 static bool_t ktpd_session_process_cmd(ktpd_session_t *ktpd, faux_msg_t *msg)
 {
 	char *line = NULL;
-	faux_msg_t *ack = NULL;
 	int retcode = -1;
 	ktp_cmd_e cmd = KTP_CMD_ACK;
 	faux_error_t *error = NULL;
@@ -128,7 +127,16 @@ static bool_t ktpd_session_process_cmd(ktpd_session_t *ktpd, faux_msg_t *msg)
 
 	rc = ktpd_session_exec(ktpd, line, &retcode, error);
 	faux_str_free(line);
+
+	// Command is scheduled. Eloop will wait for ACTION completion.
+	// So inform client about it and about command features like
+	// interactive/non-interactive.
 	if (ktpd->exec) {
+		faux_msg_t *ack = NULL;
+		ktp_status_e status = KTP_STATUS_INCOMPLETED;
+		ack = ktp_msg_preform(cmd, status);
+		faux_msg_send_async(ack, ktpd->async);
+		faux_msg_free(ack);
 		faux_error_free(error);
 		return BOOL_TRUE; // Continue and wait for ACTION
 	}
@@ -142,7 +150,7 @@ static bool_t ktpd_session_process_cmd(ktpd_session_t *ktpd, faux_msg_t *msg)
 
 	if (rc) {
 		uint8_t retcode8bit = 0;
-		ack = ktp_msg_preform(cmd, KTP_STATUS_NONE);
+		faux_msg_t *ack = ktp_msg_preform(cmd, KTP_STATUS_NONE);
 		retcode8bit = (uint8_t)(retcode & 0xff);
 		faux_msg_add_param(ack, KTP_PARAM_RETCODE, &retcode8bit, 1);
 		faux_msg_send_async(ack, ktpd->async);