diff src/cmd_proto.c @ 1:f7c60e525801

cptest and cp_ping.py to test cmd_proto.c.
author Thinker K.F. Li <thinker@branda.to>
date Sat, 21 Feb 2009 20:20:06 +0800
parents
children e410832c3280
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cmd_proto.c	Sat Feb 21 20:20:06 2009 +0800
@@ -0,0 +1,136 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "cmd_proto.h"
+
+enum {
+    ST_WAIT_MAGIC0,
+    ST_WAIT_MAGIC1,
+    ST_WAIT_SEQ,
+    ST_WAIT_LEN,
+    ST_WAIT_DATA,
+    ST_WAIT_CSUM
+};
+
+cmd_proto_t *cmd_proto_new(void) {
+    cmd_proto_t *cp;
+
+    cp = (cmd_proto_t *)malloc(sizeof(cmd_proto_t) + 512);
+    if(cp == NULL)
+	return NULL;
+    
+    memset(cp, 0, sizeof(cmd_proto_t));
+    cp->bufs[0] = ((char *)cp) + sizeof(cmd_proto_t);
+    cp->bufs[1] = ((char *)cp) + sizeof(cmd_proto_t) + 256;
+    cp->cmds[0].data = cp->bufs[0] + 1;
+    cp->cmds[1].data = cp->bufs[1] + 1;
+
+    return cp;
+}
+
+void cmd_proto_free(cmd_proto_t *cp) {
+    free(cp);
+}
+
+cp_cmd_t BAD_CMD;
+cp_cmd_t CSUM_ERR_CMD;
+
+static
+cp_cmd_t *make_cmd(cmd_proto_t *cp) {
+    char *buf = cp->bufs[cp->receiving];
+    cp_cmd_t *cmd;
+    int i;
+
+    if(buf[0] <= 0 || buf[0] >= CPCMD_MAX)
+	return &BAD_CMD;
+    
+    cmd = cp->cmds + cp->receiving;
+
+    cmd->seq = cp->seq;
+    cmd->code = buf[0];
+    cmd->data_sz = cp->len - 1;
+
+    cp->receiving ^= 1;
+    
+    return cmd;
+}
+
+#define CSUM_ADD(csum, c)					\
+    do {							\
+	csum = ((((csum) << 3) | ((csum) >> 5)) ^ (c)) & 0xff;	\
+    } while(0)
+
+cp_cmd_t *cmd_proto_rcv(cmd_proto_t *cp, int c) {
+    int i, csum;
+    char *buf;
+    cp_cmd_t *cmd = NULL;
+    
+    switch(cp->status) {
+    case ST_WAIT_MAGIC0:
+	if(c == CP_MAGIC[0])
+	    cp->status = ST_WAIT_MAGIC1;
+	break;
+	
+    case ST_WAIT_MAGIC1:
+	if(c == CP_MAGIC[1])
+	    cp->status = ST_WAIT_SEQ;
+	else if(c != CP_MAGIC[0])
+	    cp->status = ST_WAIT_MAGIC0;
+	break;
+
+    case ST_WAIT_SEQ:
+	cp->seq = c;
+	cp->status = ST_WAIT_LEN;
+	break;
+	
+    case ST_WAIT_LEN:
+	cp->len = c;
+	if(c > 0) {
+	    cp->status = ST_WAIT_DATA;
+	    cp->cnt = 0;
+	} else
+	    cp->status = ST_WAIT_CSUM;
+	break;
+	
+    case ST_WAIT_DATA:
+	cp->bufs[cp->receiving][cp->cnt++] = c;
+	if(cp->cnt >= cp->len)
+	    cp->status = ST_WAIT_CSUM;
+	break;
+	
+    case ST_WAIT_CSUM:
+	csum = 0;
+	buf = cp->bufs[cp->receiving];
+	for(i = 0; i < cp->len; i++)
+	    CSUM_ADD(csum, buf[i]);
+	CSUM_ADD(csum, c);
+	cp->status = ST_WAIT_MAGIC0;
+	if(csum == 0)
+	    cmd = make_cmd(cp);
+	else
+	    cmd = &CSUM_ERR_CMD;
+	break;
+	
+    default:
+	cp->status = ST_WAIT_MAGIC0;
+    }
+
+    return cmd;
+}
+
+int cmd_proto_cmd_fill(char *buf, int seq, cp_ccode_t code, int data_sz) {
+    int i, last = data_sz + CP_CMD_HEAD_SZ;
+    int csum = 0;
+    
+    buf[0] = CP_MAGIC[0];
+    buf[1] = CP_MAGIC[1];
+    buf[2] = seq;
+    buf[3] = data_sz + 1;
+    buf[4] = code;
+    for(i = CP_CMD_HEAD_SZ - 1; i < last; i++)
+	CSUM_ADD(csum, buf[i]);
+    CSUM_ADD(csum, 0);
+    buf[i] = csum;
+    
+    return data_sz + CP_CMD_OVERHEAD;
+}