1 #include <u.h> 2 #include <libc.h> 3 #include <venti.h> 4 #include "session.h" 5 6 static char EProtocolBotch[] = "venti protocol botch"; 7 static char ELumpSize[] = "illegal lump size"; 8 static char ENotConnected[] = "not connected to venti server"; 9 10 static Packet *vtRPC(VtSession *z, int op, Packet *p); 11 12 VtSession * 13 vtClientAlloc(void) 14 { 15 VtSession *z = vtAlloc(); 16 return z; 17 } 18 19 VtSession * 20 vtDial(char *host, int canfail) 21 { 22 VtSession *z; 23 int fd; 24 char *na; 25 char e[ERRMAX]; 26 27 if(host == nil) 28 host = getenv("venti"); 29 if(host == nil) 30 host = "$venti"; 31 32 if (host == nil) { 33 if (!canfail) 34 werrstr("no venti host set"); 35 na = ""; 36 fd = -1; 37 } else { 38 na = netmkaddr(host, 0, "venti"); 39 fd = dial(na, 0, 0, 0); 40 } 41 if(fd < 0){ 42 rerrstr(e, sizeof e); 43 if(!canfail){ 44 vtSetError("venti dialstring %s: %s", na, e); 45 return nil; 46 } 47 } 48 z = vtClientAlloc(); 49 if(fd < 0) 50 strcpy(z->fderror, e); 51 vtSetFd(z, fd); 52 return z; 53 } 54 55 int 56 vtRedial(VtSession *z, char *host) 57 { 58 int fd; 59 char *na; 60 61 if(host == nil) 62 host = getenv("venti"); 63 if(host == nil) 64 host = "$venti"; 65 66 na = netmkaddr(host, 0, "venti"); 67 fd = dial(na, 0, 0, 0); 68 if(fd < 0){ 69 vtOSError(); 70 return 0; 71 } 72 vtReset(z); 73 vtSetFd(z, fd); 74 return 1; 75 } 76 77 VtSession * 78 vtStdioServer(char *server) 79 { 80 int pfd[2]; 81 VtSession *z; 82 83 if(server == nil) 84 return nil; 85 86 if(access(server, AEXEC) < 0) { 87 vtOSError(); 88 return nil; 89 } 90 91 if(pipe(pfd) < 0) { 92 vtOSError(); 93 return nil; 94 } 95 96 switch(fork()) { 97 case -1: 98 close(pfd[0]); 99 close(pfd[1]); 100 vtOSError(); 101 return nil; 102 case 0: 103 close(pfd[0]); 104 dup(pfd[1], 0); 105 dup(pfd[1], 1); 106 execl(server, "ventiserver", "-i", nil); 107 exits("exec failed"); 108 } 109 close(pfd[1]); 110 111 z = vtClientAlloc(); 112 vtSetFd(z, pfd[0]); 113 return z; 114 } 115 116 int 117 vtPing(VtSession *z) 118 { 119 Packet *p = packetAlloc(); 120 121 p = vtRPC(z, VtQPing, p); 122 if(p == nil) 123 return 0; 124 packetFree(p); 125 return 1; 126 } 127 128 int 129 vtHello(VtSession *z) 130 { 131 Packet *p; 132 uchar buf[10]; 133 char *sid; 134 int crypto, codec; 135 136 sid = nil; 137 138 p = packetAlloc(); 139 if(!vtAddString(p, vtGetVersion(z))) 140 goto Err; 141 if(!vtAddString(p, vtGetUid(z))) 142 goto Err; 143 buf[0] = vtGetCryptoStrength(z); 144 buf[1] = 0; 145 buf[2] = 0; 146 packetAppend(p, buf, 3); 147 p = vtRPC(z, VtQHello, p); 148 if(p == nil) 149 return 0; 150 if(!vtGetString(p, &sid)) 151 goto Err; 152 if(!packetConsume(p, buf, 2)) 153 goto Err; 154 if(packetSize(p) != 0) { 155 vtSetError(EProtocolBotch); 156 goto Err; 157 } 158 crypto = buf[0]; 159 codec = buf[1]; 160 161 USED(crypto); 162 USED(codec); 163 164 packetFree(p); 165 166 vtLock(z->lk); 167 z->sid = sid; 168 z->auth.state = VtAuthOK; 169 vtSha1Free(z->inHash); 170 z->inHash = nil; 171 vtSha1Free(z->outHash); 172 z->outHash = nil; 173 vtUnlock(z->lk); 174 175 return 1; 176 Err: 177 packetFree(p); 178 vtMemFree(sid); 179 return 0; 180 } 181 182 int 183 vtSync(VtSession *z) 184 { 185 Packet *p = packetAlloc(); 186 187 p = vtRPC(z, VtQSync, p); 188 if(p == nil) 189 return 0; 190 if(packetSize(p) != 0){ 191 vtSetError(EProtocolBotch); 192 goto Err; 193 } 194 packetFree(p); 195 return 1; 196 197 Err: 198 packetFree(p); 199 return 0; 200 } 201 202 int 203 vtWrite(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n) 204 { 205 Packet *p = packetAlloc(); 206 207 packetAppend(p, buf, n); 208 return vtWritePacket(z, score, type, p); 209 } 210 211 int 212 vtWritePacket(VtSession *z, uchar score[VtScoreSize], int type, Packet *p) 213 { 214 int n = packetSize(p); 215 uchar *hdr; 216 217 if(n > VtMaxLumpSize || n < 0) { 218 vtSetError(ELumpSize); 219 goto Err; 220 } 221 222 if(n == 0) { 223 memmove(score, vtZeroScore, VtScoreSize); 224 return 1; 225 } 226 227 hdr = packetHeader(p, 4); 228 hdr[0] = type; 229 hdr[1] = 0; /* pad */ 230 hdr[2] = 0; /* pad */ 231 hdr[3] = 0; /* pad */ 232 p = vtRPC(z, VtQWrite, p); 233 if(p == nil) 234 return 0; 235 if(!packetConsume(p, score, VtScoreSize)) 236 goto Err; 237 if(packetSize(p) != 0) { 238 vtSetError(EProtocolBotch); 239 goto Err; 240 } 241 packetFree(p); 242 return 1; 243 Err: 244 packetFree(p); 245 return 0; 246 } 247 248 int 249 vtRead(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n) 250 { 251 Packet *p; 252 253 p = vtReadPacket(z, score, type, n); 254 if(p == nil) 255 return -1; 256 n = packetSize(p); 257 packetCopy(p, buf, 0, n); 258 packetFree(p); 259 return n; 260 } 261 262 Packet * 263 vtReadPacket(VtSession *z, uchar score[VtScoreSize], int type, int n) 264 { 265 Packet *p; 266 uchar buf[10]; 267 268 if(n < 0 || n > VtMaxLumpSize) { 269 vtSetError(ELumpSize); 270 return nil; 271 } 272 273 p = packetAlloc(); 274 if(memcmp(score, vtZeroScore, VtScoreSize) == 0) 275 return p; 276 277 packetAppend(p, score, VtScoreSize); 278 buf[0] = type; 279 buf[1] = 0; /* pad */ 280 buf[2] = n >> 8; 281 buf[3] = n; 282 packetAppend(p, buf, 4); 283 return vtRPC(z, VtQRead, p); 284 } 285 286 287 static Packet * 288 vtRPC(VtSession *z, int op, Packet *p) 289 { 290 uchar *hdr, buf[2]; 291 char *err; 292 293 if(z == nil){ 294 vtSetError(ENotConnected); 295 return nil; 296 } 297 298 /* 299 * single threaded for the momment 300 */ 301 vtLock(z->lk); 302 if(z->cstate != VtStateConnected){ 303 vtSetError(ENotConnected); 304 goto Err; 305 } 306 hdr = packetHeader(p, 2); 307 hdr[0] = op; /* op */ 308 hdr[1] = 0; /* tid */ 309 vtDebug(z, "client send: "); 310 vtDebugMesg(z, p, "\n"); 311 if(!vtSendPacket(z, p)) { 312 p = nil; 313 goto Err; 314 } 315 p = vtRecvPacket(z); 316 if(p == nil) 317 goto Err; 318 vtDebug(z, "client recv: "); 319 vtDebugMesg(z, p, "\n"); 320 if(!packetConsume(p, buf, 2)) 321 goto Err; 322 if(buf[0] == VtRError) { 323 if(!vtGetString(p, &err)) { 324 vtSetError(EProtocolBotch); 325 goto Err; 326 } 327 vtSetError(err); 328 vtMemFree(err); 329 packetFree(p); 330 vtUnlock(z->lk); 331 return nil; 332 } 333 if(buf[0] != op+1 || buf[1] != 0) { 334 vtSetError(EProtocolBotch); 335 goto Err; 336 } 337 vtUnlock(z->lk); 338 return p; 339 Err: 340 vtDebug(z, "vtRPC failed: %s\n", vtGetError()); 341 if(p != nil) 342 packetFree(p); 343 vtUnlock(z->lk); 344 vtDisconnect(z, 1); 345 return nil; 346 } 347