ref: 8a603a071dc58deb4ab66b76572c5a82767fa8db
dir: /server.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "neoventi.h" // Convenience function: reads a venti packed from conn into buf // Invariant: buf MUST have 0x10002 bytes available! see venti(6) static int vtrecv(VtConn conn, char *buf) { u16int len; if(read(conn.fd, buf, 2) != 2){ werrstr("Failed to read message size: %r"); return 0; } len = (buf[0] << 8 | buf[1]); if(read(conn.fd, buf + 2, len) != len){ werrstr("Failed to read message: %r"); return 0; } return 1; } static void vtversion(VtConn conn) { char c; if(fprint(conn.fd, "venti-02-neoventi\n") == 18) while(read(conn.fd, &c, 1) == 1) if(c == '\n') return; fprint(conn.fd, "FUCK OFF\n"); close(conn.fd); sysfatal("venti handshake failed: %r"); } static void vtread(VtConn conn, char *buf) { u8int *score; VtArena arena; u64int addr; u16int size; u32int off; u8int blocks; uchar *dbuf; score = (u8int*)buf + 4; if(!vtreadlookup(score, &arena, &addr, &size, &blocks)) sysfatal("todo graceful read errors"); // Response: VtRread, msg tag, data dbuf = malloc(4 + size); dbuf[0] = (size+2)>>8; dbuf[1] = (size+2) & 0xFF; dbuf[2] = VtRread; dbuf[3] = buf[3]; readclump(dbuf+4, arena, addr, blocks); if(write(conn.fd, dbuf, size + 4) != size+4) sysfatal("failed to write data"); } static int vtconnhandle(VtConn conn, char *buf) { switch(buf[2]){ case VtTread: vtread(conn, buf); return 1; case VtTgoodbye: return 0; case VtTsync: print("we don't support vtsync yet. Hanging up!\n"); return 0; default: sysfatal("TODO safely hang up vtconns"); } return 0; } static void handle(int ctl, char *dir) { char buf[0x10002]; VtConn conn; conn.fd = accept(ctl, dir); if(conn.fd < 0) sysfatal("failed to accept connection: %r"); print("received a connection at %s, fd %d\n", dir, conn.fd); vtversion(conn); if(!vtrecv(conn, buf)) sysfatal("msg recv failed: %r"); if(buf[2] != VtThello) sysfatal("received message before hello: %d", buf[2]); if(buf[4] != 0 || buf[5] != 2 || buf[6] != '0' || buf[7] != '2') sysfatal("unsupported protocol version requested in Thello: %d %d %d %d", buf[4], buf[5], buf[6], buf[7]); buf[2] = VtRhello; buf[6] = 'n'; buf[7] = 'o'; buf[1] = 8; if(write(conn.fd, buf, 10) != 10) sysfatal("failed to rhello: %r"); while(vtrecv(conn, buf)){ if(!vtconnhandle(conn, buf)) break; } close(conn.fd); } void serve(char *addr) { char adir[NETPATHLEN], dir[NETPATHLEN]; int fd, ctl; fd = announce(addr, adir); if(fd < 0) sysfatal("%r"); procsetname("neoventi/server"); for(ctl = listen(adir, dir); ctl >= 0; ctl = listen(adir, dir)){ handle(ctl, dir); close(ctl); } fprint(2, "server has died\n"); }