changeset 176:7f727aaf5cd4

rvinterf: beginning of server implementation
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sat, 23 Nov 2013 07:40:13 +0000
parents 2f214bd03119
children fef035264dd4
files .hgignore rvinterf/localsock.h rvinterf/lowlevel/Makefile rvinterf/lowlevel/client.h rvinterf/lowlevel/rvifmain.c
diffstat 5 files changed, 221 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Nov 22 20:16:00 2013 +0000
+++ b/.hgignore	Sat Nov 23 07:40:13 2013 +0000
@@ -15,6 +15,7 @@
 ^loadtools/fc-loadtool
 ^loadtools/fc-xram
 
+^rvinterf/lowlevel/rvinterf$
 ^rvinterf/lowlevel/rvtdump$
 ^rvinterf/old/etmsend$
 ^rvinterf/old/rvtdump$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rvinterf/localsock.h	Sat Nov 23 07:40:13 2013 +0000
@@ -0,0 +1,73 @@
+/*
+ * This header defines and describes (through comments) the local UNIX domain
+ * socket interface implemented between rvinterf and its clients like fc-tmsh.
+ *
+ * The UNIX domain sockets used for this ad hoc interface are of the
+ * SOCK_STREAM kind, but the true nature of the communication is message-based.
+ * We use the same trick that is used for DNS over TCP: every message in each
+ * direction is preceded by a 2-byte length.  This length and all other
+ * multibyte numbers are sent in the native byte order of the machine on which
+ * the rvinterf suite is running.  The limit on the size of these messages
+ * (for sizing buffers etc) is:
+ */
+
+#define	LOCALSOCK_MAX_MSG	1024
+
+/*
+ * Each message in the client->rvinterf direction (can be seen as command)
+ * begins (after the length) with an opcode byte as follows:
+ */
+
+#define	CLI2RVI_WANT_RVTRACE		0x00
+#define	CLI2RVI_WANT_MUXPROTO		0x01
+#define	CLI2RVI_PKT_TO_TARGET		0x02
+#define	CLI2RVI_RAWBYTES_TO_TARGET	0x03
+
+/*
+ * The first two commands (CLI2RVI_WANT_RVTRACE and CLI2RVI_WANT_MUXPROTO)
+ * are the means by which client programs inform rvinterf that they are
+ * interested in receiving copies of certain packets coming from the target.
+ *
+ * The CLI2RVI_WANT_RVTRACE opcode needs to be followed by a USEID mask value
+ * and a USEID match value, both in the native byte order of the machine
+ * running rvinterf, for a total message length of 9 bytes.  For every RV
+ * trace message received from the target, rvinterf will iterate through all
+ * active clients to see who is interested: if the received USEID ANDed with
+ * the mask equals the match value, the message will be forwarded to that
+ * client.
+ *
+ * The CLI2RVI_WANT_MUXPROTO opcode needs to be followed by one byte
+ * identifying the RVTMUX protocol of interest, i.e., the first byte of the
+ * packets exchanged between the host and the target, e.g., 0x12 for L1 traces
+ * as defined in pktmux.h, for a total message length of 2 bytes.
+ *
+ * The last two commands (CLI2RVI_PKT_TO_TARGET and CLI2RVI_RAWBYTES_TO_TARGET)
+ * cause data payload to be sent to the target serial port.  Payload following
+ * CLI2RVI_PKT_TO_TARGET (must not exceed MAX_PKT_TO_TARGET) is sent with the
+ * proper packet encapsulation per TI; bytes following
+ * CLI2RVI_RAWBYTES_TO_TARGET are sent raw.
+ */
+
+/*
+ * Each message in the rvinterf->client direction begins (after the length)
+ * with a message type byte as follows:
+ */
+
+#define	RVI2CLI_PKT_FROM_TARGET		0x00
+#define	RVI2CLI_LOCAL_CMD_RESP		0x01
+
+/*
+ * Messages beginning with RVI2CLI_PKT_FROM_TARGET are packets received
+ * from the target GSM device; the byte following this type code is the
+ * first byte of the packet from the target, e.g., 0x11 for RV traces or
+ * 0x12 for L1 traces.  Rvinterf will only start sending these messages
+ * to a client after that client has expressed interest in receiving
+ * target->host packets of a particular type.
+ *
+ * Messages beginning with RVI2CLI_LOCAL_CMD_RESP are generated locally
+ * by rvinterf itself as responses to commands, currently as responses to
+ * CLI2RVI_WANT_{RVTRACE,MUXPROTO}.  The byte following the
+ * RVT2CLI_LOCAL_CMD_RESP type code is ASCII '+' or ASCII '-', indicating
+ * success or error, respectively.  Any remaining bytes form a message
+ * for the user.
+ */
--- a/rvinterf/lowlevel/Makefile	Fri Nov 22 20:16:00 2013 +0000
+++ b/rvinterf/lowlevel/Makefile	Sat Nov 23 07:40:13 2013 +0000
@@ -1,15 +1,21 @@
 CC=	gcc
 CFLAGS=	-O2
-PROGS=	rvtdump
+PROGS=	rvtdump rvinterf
 INSTBIN=/usr/local/bin
 
 RVTDUMP_OBJS=	format.o format_g23.o openport.o output.o packetrx.o rvtdump.o
 
+RVINTERF_OBJS=	format.o format_g23.o logsent.o openport.o output.o packetrx.o \
+		packettx.o rvifmain.o
+
 all:	${PROGS}
 
 rvtdump:	${RVTDUMP_OBJS}
 	${CC} ${CFLAGS} -o $@ ${RVTDUMP_OBJS}
 
+rvinterf:	${RVINTERF_OBJS}
+	${CC} ${CFLAGS} -o $@ ${RVINTERF_OBJS}
+
 install:	${PROGS}
 	mkdir -p ${INSTBIN}
 	install -c ${PROGS} ${INSTBIN}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rvinterf/lowlevel/client.h	Sat Nov 23 07:40:13 2013 +0000
@@ -0,0 +1,23 @@
+/*
+ * The structure defined in this header file is malloced in rvinterf
+ * for every client program connection.
+ */
+
+#define	MAX_RVT_INTEREST	4
+
+typedef	unsigned u32;
+
+struct client {
+	struct	client *next;
+	struct	client **backptr;
+	int	fd;
+	int	rx_state;
+	u_char	rx_buf[LOCALSOCK_MAX_MSG];
+	int	rx_msglen;
+	u_char	*rx_ptr;
+	int	rx_left;
+	int	int_rvt_count;
+	u32	int_rvt_mask[MAX_RVT_INTEREST];
+	u32	int_rvt_match[MAX_RVT_INTEREST];
+	char	int_proto[8];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rvinterf/lowlevel/rvifmain.c	Sat Nov 23 07:40:13 2013 +0000
@@ -0,0 +1,117 @@
+/*
+ * This module contains the main() function for rvinterf
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include "../pktmux.h"
+
+extern int target_fd;
+extern char *baudrate_name;
+
+extern u_char rxpkt[];
+extern size_t rxpkt_len;
+
+char *logfname;
+FILE *logF;
+time_t logtime;
+int background;
+
+main(argc, argv)
+	char **argv;
+{
+	extern char *optarg;
+	extern int optind;
+	int c;
+	fd_set fds;
+
+	while ((c = getopt(argc, argv, "bB:d:l:")) != EOF)
+		switch (c) {
+		case 'b':
+			background++;
+			continue;
+		case 'B':
+			baudrate_name = optarg;
+			continue;
+		case 'd':
+			target_fd = atoi(optarg);
+			continue;
+		case 'l':
+			logfname = optarg;
+			continue;
+		case '?':
+		default:
+usage:			fprintf(stderr,
+				"usage: %s [options] ttyport\n", argv[0]);
+			exit(1);
+		}
+	if (target_fd <= 0) {
+		if (argc - optind != 1)
+			goto usage;
+		open_target_serial(argv[optind]);
+	}
+
+	set_serial_nonblock(0);
+	setlinebuf(stdout);
+	if (logfname) {
+		logF = fopen(logfname, "w");
+		if (!logF) {
+			perror(logfname);
+			exit(1);
+		}
+		fprintf(logF, "*** Log of rvinterf session ***\n");
+		setlinebuf(logF);
+	}
+	if (background) {
+		c = fork();
+		if (c < 0) {
+			perror("fork");
+			exit(1);
+		}
+		if (c) {
+			printf("rvinterf forked into background (pid %d)\n", c);
+			exit(0);
+		}
+	}
+	for (;;) {
+		FD_ZERO(&fds);
+		FD_SET(target_fd, &fds);
+		c = select(target_fd+1, &fds, 0, 0, 0);
+		time(&logtime);
+		if (c < 0) {
+			if (errno == EINTR)
+				continue;
+			perror("select");
+			exit(1);
+		}
+		if (FD_ISSET(target_fd, &fds))
+			process_serial_rx();
+	}
+}
+
+handle_rx_packet()
+{
+	switch (rxpkt[0]) {
+	case RVT_RV_HEADER:
+		if (rxpkt_len < 6)
+			goto unknown;
+		print_rv_trace();
+		return;
+	case RVT_L1_HEADER:
+		print_l1_trace();
+		return;
+	case RVT_L23_HEADER:
+		print_g23_trace();
+		return;
+	case RVT_TM_HEADER:
+		print_etm_output_raw();
+		return;
+	default:
+	unknown:
+		print_unknown_packet();
+	}
+}