#define TVERSION 100 #define TAUTH 102 #define TATTACH 104 #define TERROR 106 #define TFLUSH 108 #define TWALK 110 #define TOPEN 112 #define TCREATE 114 #define TREAD 116 #define TWRITE 118 #define TCLUNK 120 #define TREMOVE 122 #define TSTAT 124 #define TWSTAT 126 #define NT_BUF_SIZE 65536 #define NT_FIFO_SIZE 128 #define SET_REQUEST_SIZE U32 request_size = *(data)(U32*); #define NT_IS_DIR 0x80 #define NT_IS_FILE 0x0 // #define SET_RESPONSE_SIZE *(nt->out)(U32*) = response_size; // #define CLEAR_RESPONSE_BUFFER MemSet(nt->out, NULL, response_size); // #define SEND_RESPONSE_BUFFER nt->s->send(nt->out, response_size); #define SET_RESPONSE_CMD nt->out[4] = data[4] + 1; #define SET_RESPONSE_TAG \ nt->out[5] = data[5]; \ nt->out[6] = data[6]; #define SET_MSGS \ @9p_msg * Tmsg = data; \ @9p_msg * Rmsg = nt->out; #define SEND_RMSG \ SET_RESPONSE_CMD SET_RESPONSE_TAG @9p_debug_dump(Rmsg, Rmsg->length, 1); \ nt->s->send(Rmsg, Rmsg->length); #define CLEAR_RMSG MemSet(Rmsg(U64) + 4, NULL, Rmsg->length - 4); U8* @nt_msg_type_string(I64 req) { switch (req) { case TVERSION: return "Tversion"; case TAUTH: return "Tauth"; case TATTACH: return "Tattach"; case TERROR: return "Terror"; case TFLUSH: return "Tflush"; case TWALK: return "Twalk"; case TOPEN: return "Topen"; case TCREATE: return "Tcreate"; case TREAD: return "Tread"; case TWRITE: return "Twrite"; case TCLUNK: return "Tclunk"; case TREMOVE: return "Tremove"; case TSTAT: return "Tstat"; case TWSTAT: return "Twstat"; default: return "(unimplemented)"; } } class @9p_qid { U8 type; U32 version; U64 path; }; class @9p_str { U8 length; U8 data; }; class @9p_msg { U32 length; U8 type; U16 tag; U32 fid; }; class @9p_twalk : @9p_msg { U32 newfid; U16 nwname; U8 wname; // mem location for nwname*(wname[s]) }; class @9p_stat { U16 size; U16 type; U32 dev; @9p_qid qid; U32 mode; U32 atime; U32 mtime; U64 length; U8 name; }; class @9p_direntry { U16 type; U32 dev; @9p_qid qid; U32 mode; U32 atime; U32 mtime; U64 length; U8 name; }; // The reply will contain a machine-independent directory entry, stat, laid out as follows: // size[2]total byte count of the following data // type[2]for kernel use // dev[4]for kernel use // qid.type[1] // the type of the file (directory, etc.), represented as a bit vector corresponding to the high 8 bits of the file’s mode word. // qid.vers[4] // version number for given path // qid.path[8] // the file server’s unique identification for the file // mode[4] // permissions and flags // atime[4] // last access time // mtime[4] // last modification time // length[8] // length of file in bytes // name[ s ] // file name; must be / if the file is the root directory of the server // uid[ s ]owner name // gid[ s ]group name // muid[ s ] // name of the user who last modified the file U64 EndianU64(U64 s) { U64 d; d.u8[0] = s.u8[7]; d.u8[1] = s.u8[6]; d.u8[2] = s.u8[5]; d.u8[3] = s.u8[4]; d.u8[4] = s.u8[3]; d.u8[5] = s.u8[2]; d.u8[6] = s.u8[1]; d.u8[7] = s.u8[0]; return d; } // Mouse Cursor CDC* @nt_cursor = DCNew(16, 16); Free(@nt_cursor->body); U8 @nt_cursor_data[16 * 16] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @nt_cursor->body = @nt_cursor_data; class @nt { CDC* cursor; CTask* dbg_task; CTask* main_task; CTask* rx_task; CTask* tx_task; TcpSocket* s; U8* host; I64 port; U8* out; CFifoI64* rx_fifo; CFifoI64* rx_dbg_fifo; CFifoI64* tx_dbg_fifo; CFifoI64* kbd_fifo; I64 kbd_last_jiffies; U8* connect_script; U16 kbd_read_tag; // U8 last_kbd_read_request[23]; JsonObject* fids; JsonObject* qids; JsonObject* drawobjs; CDC* screen; I64 attach_fid; }; class @nt_dbg_msg { I64 ts; U8* s; I64 dir; }; U0 @nt_dbg_out(@nt_dbg_msg* msg) { U8 ts[16]; StrPrint(ts, "[%8d] %c ", msg->ts, @t(msg->dir, 'TX', 'RX')); U8* s = ts; while (*s) { OutU8(0xe9, *s++); } s = msg->s; while (*s) { OutU8(0xe9, *s++); } OutU8(0xe9, '\n'); // Free(msg->s); // Free(msg); } @9p_qid * @nt_qid_create(@nt* nt, U8* path, I64 type) { @9p_qid * qid = CAlloc(sizeof(@9p_qid), nt->main_task); qid->type = type; qid->path = StrNew(path, nt->main_task); nt->qids->set(path, qid, JSON_NUMBER); return qid; } @9p_qid * @nt_lookup_qid_by_path(@nt* nt, U8* path) { return nt->qids->@(path); } U0 @nt_pascal_to_c_strings(@nt* nt, U8** wname, U8* data, I64 nwname) { I64 i, j = 0; I64 len = 0; for (i = 0; i < nwname; i++) { len = *(data + j)(U16*); j += 2; wname[i] = CAlloc(len + 1, nt->main_task); MemCpy(wname[i], data + j, len); j += len; } } U0 @nt_rx_dbg(@nt* nt, U8* fmt, ...) { U8* buf; if (argc) { buf = StrPrintJoin(NULL, fmt, argc, argv); } else { buf = StrNew(fmt); } @nt_dbg_msg* msg = CAlloc(sizeof(@nt_dbg_msg), nt->main_task); msg->ts = cnts.jiffies; msg->s = buf; msg->dir = 0; FifoI64Ins(nt->rx_dbg_fifo, msg); } U0 @nt_tx_dbg(@nt* nt, U8* fmt, ...) { U8* buf; if (argc) { buf = StrPrintJoin(NULL, fmt, argc, argv); } else { buf = StrNew(fmt); } @nt_dbg_msg* msg = CAlloc(sizeof(@nt_dbg_msg), nt->main_task); msg->ts = cnts.jiffies; msg->s = buf; msg->dir = 1; FifoI64Ins(nt->tx_dbg_fifo, msg); } U0 @nt_zrmsg(@nt* nt, I64 length) { // Zero Rmsg to length and set length @9p_msg * Rmsg = nt->out; MemSet(Rmsg, NULL, length); Rmsg->length = length; } U0 @nt_fid_set(@nt* nt, U8* fidbuf, @9p_qid * qid) { JsonObject* fid = Json.CreateObject(nt->main_task); fid->set("qid", qid, JSON_NUMBER); nt->fids->set(fidbuf, fid, JSON_OBJECT); }