shithub: svcfs

Download patch

ref: f96a13204b5f5910880b73bc1747b40d42d2755f
parent: f7c354bfa6b8cffe2ce4880712decd29a4f22106
author: Michael Misch <michaelmisch1985@gmail.com>
date: Sat Aug 10 00:03:27 EDT 2024

Updates found while integrating

--- a/alt.h
+++ b/alt.h
@@ -1,13 +1,34 @@
 typedef struct Buffer Buffer;
 typedef struct Notify Notify;
+typedef struct Cmd Cmd;
 
+enum
+{
+	CloneCmd,
+	CreateCmd,
+	DeleteCmd,
+	RemoveCmd,
+	NotifyCmd,
+	ErrorCmd,
+	StatusCmd,
+	SideCmd,
+	NavCmd,
+	TitleCmd,
+	ImageCmd,
+	FeedCmd,
+	QuitCmd,
+	ServiceCmd,
+
+	MaxBuflen = 256,
+};
+
 struct Buffer
 {
 	QLock       l;
-	char	*name;
+	char	name[MaxBuflen];
 	char	title[1024];
 	char	status[1024];
-	char	aside[1024];
+	char	*aside;
 	int	fd;	// feed
 	int	tag;	// feed
 	int	unread;
@@ -23,6 +44,15 @@
 	Notify	*next;
 };
 
+struct Cmd
+{
+	// Potentially big
+	int	type;
+	char	buffer[MaxBuflen];
+	char	data[2048];
+	char	svccmd[256];
+};
+
 Buffer *bufferCreate(Channel*);
 Buffer *bufferSearch(Buffer*, char*);
 Buffer *bufferSearchTag(Buffer*, ulong);
@@ -42,6 +72,7 @@
 char *logdir;
 int debug;
 
+Cmd* convS2C(char*);
 void clattach(Req*);
 void clstat(Req*);
 char *clwalk1(Fid*, char*, Qid*);
--- a/buffer.c
+++ b/buffer.c
@@ -51,14 +51,11 @@
 	}
 	
 	b = mallocz(sizeof(*b), 1);
-	b->name = estrdup(name);
+	strcpy(b->name, name);
 	b->notify = nil;
 	b->unread = 0;
 	b->tag = -1;
 	b->rz.l = &b->l;
-	memset(b->title, 0, sizeof(b->title));
-	memset(b->status, 0, sizeof(b->status));
-	memset(b->aside, 0, sizeof(b->aside));
 	snprint(p, sizeof(p), "%s/%s/%s", logdir, base->name, name);
 	if(access(p, 0) == 0)
 		b->fd = open(p, OWRITE);
@@ -104,10 +101,6 @@
 	Buffer *b;
 
 	b = mallocz(sizeof(*b), 1);
-	b->name = nil;
-	memset(b->title, 0, sizeof(b->title));
-	memset(b->status, 0, sizeof(b->status));
-	memset(b->aside, 0, sizeof(b->aside));
 	b->cmds = cmds;
 	b->tag = -1;
 	b->unread = 0;
--- a/client.c
+++ b/client.c
@@ -343,7 +343,7 @@
 			f->cl->current = b;
 			b->tag = r->tag;
 			qunlock(&b->l);
-			memset(path, sizeof(path), 0);
+			memset(path, 0, sizeof(path));
 			snprint(path, sizeof(path), "%s/%s/%s", logdir, root->name, s);
 			f->cl->fd = open(path, OREAD);
 			r->fid->aux = f;
@@ -361,9 +361,8 @@
 			respond(r, nil);
 		} else {
 			snprint(path, sizeof(path), "%s %s", t, s);
-			srvrelease(fs);
 			send(root->cmds, path);
-			srvacquire(fs);
+			send(root->cmds, nil);
 			respond(r, nil);
 		}
 		return;
@@ -373,10 +372,13 @@
 			return;
 		}
 		n = r->ofcall.count = r->ifcall.count;
-		n += strlen(f->cl->current->name) + 7;
-		snprint(path, n, "input %s\n%s", f->cl->current->name, r->ifcall.data);
+		n += strlen(f->cl->current->name) + 8;
+		memset(path, 0, sizeof(path));
+		snprint(path, n, "input %s\n%s\n", f->cl->current->name, r->ifcall.data);
 		send(root->cmds, path);
+		send(root->cmds, nil);
 		respond(r, nil);
+
 		return;
 	}
 	respond(r, "not implemented");
--- /dev/null
+++ b/convS2C.c
@@ -1,0 +1,146 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "alt.h"
+
+struct state
+{
+	Cmd cmd;
+	char *base;
+	int size;
+	int (*fn)(struct state *s);	
+};
+
+static int parse_cmd(struct state *s);
+static int parse_from(struct state *s);
+static int parse_data(struct state *s);
+
+Cmd*
+convS2C(char *c)
+{
+	struct state s;
+	Cmd cmd;
+
+	s.fn = (*parse_cmd);
+	s.cmd.type = ErrorCmd;
+	strcpy(s.cmd.data, "An unknown error has occured");
+	s.base = c;
+	s.size = strlen(c);
+	while((s.fn(&s) > 0));
+
+	cmd.type = s.cmd.type;
+	strcpy(cmd.buffer, s.cmd.buffer);
+	strcpy(cmd.data, s.cmd.data);
+	strcpy(cmd.svccmd, s.cmd.svccmd);
+
+	return &cmd;
+}
+
+static int
+parse_cmd(struct state *s)
+{
+	int n;
+
+	n = 0;
+	for(;;){
+		if(n > s->size)
+			return -1;
+		switch(s->base[n]){
+		case '\0':
+		case '\r':
+		case '\n':
+			// Check we aren't at "quit"
+			s->base[n] = '\0';
+			s->cmd.type = CloneCmd;
+			if(strncmp("quit", s->base, n) == 0)
+				s->cmd.type = QuitCmd;
+			else
+				strcpy(s->cmd.data, s->base);
+			return 0;
+		case ' ':
+		case '\t':
+			// The overwhelming majority will be feed activity
+			if(strncmp(s->base, "feed", 4) == 0)
+				s->cmd.type = FeedCmd;
+			else if(strncmp(s->base, "aside", 5) == 0)
+				s->cmd.type = SideCmd;
+			else if(strncmp(s->base, "nav", 3) == 0)
+				s->cmd.type = NavCmd;
+			else if(strncmp(s->base, "title", 5) == 0)
+				s->cmd.type = TitleCmd;
+			else if(strncmp(s->base, "image", 5) == 0)
+				s->cmd.type = ImageCmd;
+			else if(strncmp(s->base, "delete", 6) == 0)
+				s->cmd.type = DeleteCmd;
+			else if(strncmp(s->base, "remove", 6) == 0)
+				s->cmd.type = RemoveCmd;
+			else if(strncmp(s->base, "notification", 12) == 0)
+				s->cmd.type = NotifyCmd;
+			else if(strncmp(s->base, "error", 5) == 0)
+				s->cmd.type = ErrorCmd;
+			else if(strncmp(s->base, "status", 6) == 0)
+				s->cmd.type = StatusCmd;
+			else if(strncmp(s->base, "create", 6) == 0)
+				s->cmd.type = CreateCmd;
+			else {
+				s->cmd.type = ServiceCmd;
+				strncpy(s->cmd.svccmd, s->base, n);
+			}
+			s->size -= n;
+			n++;
+			s->base += n;
+			s->fn = (*parse_from);
+			return 1;
+		default:
+			n++;
+		}
+	}
+}
+
+static int
+parse_from(struct state *s)
+{
+	int n;
+	n = 0;
+	for(;;){
+		if(n > s->size || n > MaxBuflen)
+			return -1;
+		switch(s->base[n]){
+		// leading spaces/tabs, ignore
+		case ' ':
+		case '\t':
+			// NOTE: This moves our pointer forward so n++ isn't necessary
+			s->size--;
+			s->base++;
+			break;
+		case '\0':
+			strncpy(s->cmd.buffer, s->base, n);
+			return 0;
+		case '\n':
+		case '\r':
+			s->base[n] = '\0';
+			strncpy(s->cmd.buffer, s->base, n+1);
+			// return if we have no data to parse
+			if (n >= s->size)
+				return 0;
+			s->size -=n;
+			n++;
+			s->base += n;
+			s->fn = (*parse_data);
+			return 1;
+		default:
+			n++;
+		}
+	}
+}
+
+static int
+parse_data(struct state *s)
+{
+	// We may eventually do some processing here
+	strncpy(s->cmd.data, s->base, s->size);
+	s->cmd.data[s->size] ='\0';
+	return 0;	
+}
--- a/mkfile
+++ b/mkfile
@@ -11,6 +11,7 @@
 	fs.$O\
 	buffer.$O\
 	client.$O\
+	convS2C.$O\
 	service.$O\
 	notification.$O\
 	tabs.$O\
--- a/service.c
+++ b/service.c
@@ -300,20 +300,18 @@
 		memset(buf, 0, sizeof(buf));
 		// NOTE: This stays here so we always get a good ID back on the client from the initial read
 		if(!f->svc->isInitialized) {
-			while(nbrecv(f->svc->cmds, nil) == 1)
-				;
 			snprint(buf, sizeof(buf), "%d\n", SERVICEID(f->svc));
 			readstr(r, buf);
 			respond(r, nil);
 		} else {
+			// Wait for any data/command from the client
 			srvrelease(fs);
 			recv(f->svc->cmds, buf);
-			if(strcmp(buf, "flush") == 0)
+			srvacquire(fs);
+			if(strcmp(buf, "flush") != 0)
 				readstr(r, buf);
 			respond(r, nil);
-			srvacquire(fs);
 		}
-
 		return;
 
 	}
@@ -320,72 +318,16 @@
 	respond(r, "not implemented");
 }
 
-static char*
-svcctl(Service *svc, char *s, char *data)
-{
-	// Probably notifications as well?
-	Buffer *b;
-	Dir *d;
-	char *cmd, *targ;
 
-	cmd = strtok(s, " ");
-	targ = strtok(nil, "\n");
-	if(strcmp(cmd, "feed")==0) { 
-		if(b = bufferSearch(svc->base, targ)) {
-print("%s %s %s\n", cmd, targ, data);
-			qlock(&b->l);
-			d = dirfstat(b->fd);
-			pwrite(b->fd, data, strlen(data), d->length);
-			free(d);
-			if(rwakeupall(&b->rz) == 0)
-				b->unread++;
-			qunlock(&b->l);
-			return nil;
-		}
-		return "buffer not found";
-	} else if(strcmp(cmd, "status")==0){
-		if(b = bufferSearch(svc->base, targ)) {
-			strcpy(b->status, data);
-			return nil;
-		}
-		return "buffer not found";
-	} else if(strcmp(cmd, "title")==0){
-		if(b = bufferSearch(svc->base, targ)) {
-			strcpy(b->title, data);
-			return nil;
-		}
-		return "buffer not found";
-	} else if(strcmp(cmd, "status")==0){
-		if(b = bufferSearch(svc->base, targ)) {
-			strcpy(b->status, data);
-			return nil;
-		}
-		return "buffer not found";
-	} else if(strcmp(cmd, "aside")==0){
-		if(b = bufferSearch(svc->base, targ)) {
-			strcpy(b->aside, data);
-			return nil;
-		}
-		return "buffer not found";
-	} else if(strcmp(cmd, "notify")==0){
-		// Create notification here
-		return "not yet implemented";
-	} else if(strcmp(cmd, "create")==0)
-		return bufferPush(svc->base, targ);
-	else if(strcmp(cmd, "close")==0)
-		return bufferDrop(svc->base, targ);
-	else if(strcmp(cmd, "error")==0)
-		return targ;
-	else 
-		return "command not supported";
-}
-
 void
 svcwrite(Req *r)
 {
 	int n;
-	char *s, *t;
 	Svcfid *f;
+	Cmd *c;
+	Buffer *b;
+	Dir *d;
+	char *p;
 	char path[1024];
 
 	f = r->fid->aux;
@@ -392,36 +334,71 @@
 
 	if(f->level == Qctl){
 		n = r->ofcall.count = r->ifcall.count;
-		s = mallocz(n+1, 1);
-		memmove(s, r->ifcall.data, n);
-		while(n > 0 && strchr("\r\n", s[n-1]))
-			n--;
-		s[n] = 0;
-		if(f->svc->isInitialized){
-			t = s;
-print("s in: %s\n", s);
-			while(*t && strchr("\t\r\n", *t)==0)
-				t++;
-			//while(*t && strchr("\t\r\n", *t))
-			//	*t++ = 0;
-			t = svcctl(f->svc, s, t);
-			respond(r, t);
-		} else {
-			f->svc->name = estrdup(s);
-			f->svc->base->name = estrdup(s);
-			memset(path, 0, sizeof(path));
-			snprint(path, sizeof(path), "%s/%s", logdir, s);
-			close(create(path, OREAD, DMDIR | 0755));
-			clfs.aux = f->svc->base;
-			f->svc->childpid = threadpostsrv(&clfs, s);
-			if(f->svc->childpid >= 0){
-				f->svc->isInitialized++;
-				r->fid->aux = f;
-				respond(r, nil);
-			} else 
-				respond(r, "Unable to post to srv");
+		p = mallocz(n+1, 1);
+		memmove(p, r->ifcall.data, n);
+		c = convS2C(p);
+		if(c == nil){
+			respond(r, "unable to parse command");
+			return;
 		}
-		free(s);
+		switch(c->type){
+		case CloneCmd:
+			if(!f->svc->isInitialized){
+				f->svc->name = estrdup(c->data);
+				strcpy(f->svc->base->name, c->data);
+				memset(path, 0, sizeof(path));
+				snprint(path, sizeof(path), "%s/%s", logdir, c->data);
+				close(create(path, OREAD, DMDIR | 0755));
+				clfs.aux = f->svc->base;
+				f->svc->childpid = threadpostsrv(&clfs, strdup(c->data));
+				if(f->svc->childpid >= 0){
+					f->svc->isInitialized++;
+					r->fid->aux = f;
+					respond(r, nil);
+				} else 
+					respond(r, "Unable to post to srv");
+				return;	
+			}
+			// Ignore, something weird going on.
+			respond(r, nil);
+			return;
+		case CreateCmd:
+			respond(r, bufferPush(f->svc->base, c->buffer));
+			return;
+		case NotifyCmd:
+			respond(r, "not implemented yet");
+			return;
+		case DeleteCmd:
+			respond(r, bufferDrop(f->svc->base, c->buffer));
+			return;
+		case ErrorCmd:
+			respond(r, "not implemented yet");
+			return;
+		}
+		if(b = bufferSearch(f->svc->base, c->buffer)) {
+			qlock(&b->l);
+			switch(c->type){
+			case FeedCmd:
+				d = dirfstat(b->fd);
+				pwrite(b->fd, c->data, strlen(c->data), d->length);
+				free(d);
+				if(rwakeupall(&b->rz) == 0)
+					b->unread++;
+				break;
+			case StatusCmd:
+				strcpy(b->status, c->data);
+				break;
+			case TitleCmd:
+				strcpy(b->title, c->data);
+				break;
+			case SideCmd:
+				strcpy(b->aside, c->data);
+				break;
+			}
+			qunlock(&b->l);
+			respond(r, nil);
+		} else
+			respond(r, "buffer not found");
 		return;
 	}
 	respond(r, "not implemented");
@@ -430,12 +407,11 @@
 void
 svcflush(Req *r)
 {
-	Buffer *b;
 	int i;
 	for(i = 0; i < nservice; i++)
 		if(service[i].ref > 0)
-			if((b = bufferSearchTag(service[i].base, r->tag))){
-				send(service[i].cmds, "flush");
+			if((bufferSearchTag(service[i].base, r->tag))){
+				nbsend(service[i].cmds, "flush");
 				break;
 			}
 	respond(r, nil);
--