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