Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
5 int ventidoublechecksha1 = 1;
7 static int
8 vtfcallrpc(VtConn *z, VtFcall *ou, VtFcall *in)
9 {
10 Packet *p;
12 p = vtfcallpack(ou);
13 if(p == nil)
14 return -1;
15 if((p = _vtrpc(z, p, ou)) == nil)
16 return -1;
17 if(vtfcallunpack(in, p) < 0){
18 packetfree(p);
19 return -1;
20 }
21 if(chattyventi)
22 fprint(2, "%s <- %F\n", argv0, in);
23 if(in->msgtype == VtRerror){
24 werrstr(in->error);
25 vtfcallclear(in);
26 packetfree(p);
27 return -1;
28 }
29 if(in->msgtype != ou->msgtype+1){
30 werrstr("type mismatch: sent %c%d got %c%d",
31 "TR"[ou->msgtype&1], ou->msgtype>>1,
32 "TR"[in->msgtype&1], in->msgtype>>1);
33 vtfcallclear(in);
34 packetfree(p);
35 return -1;
36 }
37 packetfree(p);
38 return 0;
39 }
41 int
42 vthello(VtConn *z)
43 {
44 VtFcall tx, rx;
46 memset(&tx, 0, sizeof tx);
47 tx.msgtype = VtThello;
48 tx.version = z->version;
49 tx.uid = z->uid;
50 if(tx.uid == nil)
51 tx.uid = "anonymous";
52 if(vtfcallrpc(z, &tx, &rx) < 0)
53 return -1;
54 z->sid = rx.sid;
55 rx.sid = 0;
56 vtfcallclear(&rx);
57 return 0;
58 }
60 Packet*
61 vtreadpacket(VtConn *z, uchar score[VtScoreSize], uint type, int n)
62 {
63 VtFcall tx, rx;
65 if(memcmp(score, vtzeroscore, VtScoreSize) == 0)
66 return packetalloc();
68 if(z == nil){
69 werrstr("not connected");
70 return nil;
71 }
73 if(z->version[1] == '2' && n >= (1<<16)) {
74 werrstr("read count too large for protocol");
75 return nil;
76 }
77 memset(&tx, 0, sizeof tx);
78 tx.msgtype = VtTread;
79 tx.blocktype = type;
80 tx.count = n;
81 memmove(tx.score, score, VtScoreSize);
82 if(vtfcallrpc(z, &tx, &rx) < 0)
83 return nil;
84 if(packetsize(rx.data) > n){
85 werrstr("read returned too much data");
86 packetfree(rx.data);
87 return nil;
88 }
89 if(ventidoublechecksha1){
90 packetsha1(rx.data, tx.score);
91 if(memcmp(score, tx.score, VtScoreSize) != 0){
92 werrstr("read asked for %V got %V", score, tx.score);
93 packetfree(rx.data);
94 return nil;
95 }
96 }
97 return rx.data;
98 }
100 int
101 vtread(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n)
103 int nn;
104 Packet *p;
106 if((p = vtreadpacket(z, score, type, n)) == nil)
107 return -1;
108 nn = packetsize(p);
109 if(packetconsume(p, buf, nn) < 0)
110 abort();
111 packetfree(p);
112 return nn;
115 int
116 vtwritepacket(VtConn *z, uchar score[VtScoreSize], uint type, Packet *p)
118 VtFcall tx, rx;
120 if(packetsize(p) == 0){
121 memmove(score, vtzeroscore, VtScoreSize);
122 return 0;
124 tx.msgtype = VtTwrite;
125 tx.blocktype = type;
126 tx.data = p;
127 if(ventidoublechecksha1)
128 packetsha1(p, score);
129 if(vtfcallrpc(z, &tx, &rx) < 0)
130 return -1;
131 if(ventidoublechecksha1){
132 if(memcmp(score, rx.score, VtScoreSize) != 0){
133 werrstr("sha1 hash mismatch: want %V got %V", score, rx.score);
134 return -1;
136 }else
137 memmove(score, rx.score, VtScoreSize);
138 return 0;
141 int
142 vtwrite(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n)
144 Packet *p;
145 int nn;
147 p = packetforeign(buf, n, 0, nil);
148 nn = vtwritepacket(z, score, type, p);
149 packetfree(p);
150 return nn;
153 int
154 vtsync(VtConn *z)
156 VtFcall tx, rx;
158 tx.msgtype = VtTsync;
159 return vtfcallrpc(z, &tx, &rx);
162 int
163 vtping(VtConn *z)
165 VtFcall tx, rx;
167 tx.msgtype = VtTping;
168 return vtfcallrpc(z, &tx, &rx);
171 int
172 vtconnect(VtConn *z)
174 if(vtversion(z) < 0)
175 return -1;
176 if(vthello(z) < 0)
177 return -1;
178 return 0;
181 int
182 vtgoodbye(VtConn *z)
184 VtFcall tx, rx;
186 tx.msgtype = VtTgoodbye;
187 vtfcallrpc(z, &tx, &rx); /* always fails: no VtRgoodbye */
188 return 0;