1 #include <u.h> 2 #include <libc.h> 3 #include <venti.h> 4 #include "session.h" 5 6 static char EAuthState[] = "bad authentication state"; 7 static char ENotServer[] = "not a server session"; 8 static char EVersion[] = "incorrect version number"; 9 static char EProtocolBotch[] = "venti protocol botch"; 10 11 VtSession * 12 vtServerAlloc(VtServerVtbl *vtbl) 13 { 14 VtSession *z = vtAlloc(); 15 z->vtbl = vtMemAlloc(sizeof(VtServerVtbl)); 16 *z->vtbl = *vtbl; 17 return z; 18 } 19 20 static int 21 srvHello(VtSession *z, char *version, char *uid, int , uchar *, int , uchar *, int ) 22 { 23 vtLock(z->lk); 24 if(z->auth.state != VtAuthHello) { 25 vtSetError(EAuthState); 26 goto Err; 27 } 28 if(strcmp(version, vtGetVersion(z)) != 0) { 29 vtSetError(EVersion); 30 goto Err; 31 } 32 vtMemFree(z->uid); 33 z->uid = vtStrDup(uid); 34 z->auth.state = VtAuthOK; 35 vtUnlock(z->lk); 36 return 1; 37 Err: 38 z->auth.state = VtAuthFailed; 39 vtUnlock(z->lk); 40 return 0; 41 } 42 43 44 static int 45 dispatchHello(VtSession *z, Packet **pkt) 46 { 47 char *version, *uid; 48 uchar *crypto, *codec; 49 uchar buf[10]; 50 int ncrypto, ncodec, cryptoStrength; 51 int ret; 52 Packet *p; 53 54 p = *pkt; 55 56 version = nil; 57 uid = nil; 58 crypto = nil; 59 codec = nil; 60 61 ret = 0; 62 if(!vtGetString(p, &version)) 63 goto Err; 64 if(!vtGetString(p, &uid)) 65 goto Err; 66 if(!packetConsume(p, buf, 2)) 67 goto Err; 68 cryptoStrength = buf[0]; 69 ncrypto = buf[1]; 70 crypto = vtMemAlloc(ncrypto); 71 if(!packetConsume(p, crypto, ncrypto)) 72 goto Err; 73 74 if(!packetConsume(p, buf, 1)) 75 goto Err; 76 ncodec = buf[0]; 77 codec = vtMemAlloc(ncodec); 78 if(!packetConsume(p, codec, ncodec)) 79 goto Err; 80 81 if(packetSize(p) != 0) { 82 vtSetError(EProtocolBotch); 83 goto Err; 84 } 85 if(!srvHello(z, version, uid, cryptoStrength, crypto, ncrypto, codec, ncodec)) { 86 packetFree(p); 87 *pkt = nil; 88 } else { 89 if(!vtAddString(p, vtGetSid(z))) 90 goto Err; 91 buf[0] = vtGetCrypto(z); 92 buf[1] = vtGetCodec(z); 93 packetAppend(p, buf, 2); 94 } 95 ret = 1; 96 Err: 97 vtMemFree(version); 98 vtMemFree(uid); 99 vtMemFree(crypto); 100 vtMemFree(codec); 101 return ret; 102 } 103 104 static int 105 dispatchRead(VtSession *z, Packet **pkt) 106 { 107 Packet *p; 108 int type, n; 109 uchar score[VtScoreSize], buf[4]; 110 111 p = *pkt; 112 if(!packetConsume(p, score, VtScoreSize)) 113 return 0; 114 if(!packetConsume(p, buf, 4)) 115 return 0; 116 type = buf[0]; 117 n = (buf[2]<<8) | buf[3]; 118 if(packetSize(p) != 0) { 119 vtSetError(EProtocolBotch); 120 return 0; 121 } 122 packetFree(p); 123 *pkt = (*z->vtbl->read)(z, score, type, n); 124 return 1; 125 } 126 127 static int 128 dispatchWrite(VtSession *z, Packet **pkt) 129 { 130 Packet *p; 131 int type; 132 uchar score[VtScoreSize], buf[4]; 133 134 p = *pkt; 135 if(!packetConsume(p, buf, 4)) 136 return 0; 137 type = buf[0]; 138 if(!(z->vtbl->write)(z, score, type, p)) { 139 *pkt = 0; 140 } else { 141 *pkt = packetAlloc(); 142 packetAppend(*pkt, score, VtScoreSize); 143 } 144 return 1; 145 } 146 147 static int 148 dispatchSync(VtSession *z, Packet **pkt) 149 { 150 (z->vtbl->sync)(z); 151 if(packetSize(*pkt) != 0) { 152 vtSetError(EProtocolBotch); 153 return 0; 154 } 155 return 1; 156 } 157 158 int 159 vtExport(VtSession *z) 160 { 161 Packet *p; 162 uchar buf[10], *hdr; 163 int op, tid, clean; 164 165 if(z->vtbl == nil) { 166 vtSetError(ENotServer); 167 return 0; 168 } 169 170 /* fork off slave */ 171 switch(rfork(RFNOWAIT|RFMEM|RFPROC)){ 172 case -1: 173 vtOSError(); 174 return 0; 175 case 0: 176 break; 177 default: 178 return 1; 179 } 180 181 182 p = nil; 183 clean = 0; 184 vtAttach(); 185 if(!vtConnect(z, nil)) 186 goto Exit; 187 188 vtDebug(z, "server connected!\n"); 189 if(0) vtSetDebug(z, 1); 190 191 for(;;) { 192 p = vtRecvPacket(z); 193 if(p == nil) { 194 break; 195 } 196 vtDebug(z, "server recv: "); 197 vtDebugMesg(z, p, "\n"); 198 199 if(!packetConsume(p, buf, 2)) { 200 vtSetError(EProtocolBotch); 201 break; 202 } 203 op = buf[0]; 204 tid = buf[1]; 205 switch(op) { 206 default: 207 vtSetError(EProtocolBotch); 208 goto Exit; 209 case VtQPing: 210 break; 211 case VtQGoodbye: 212 clean = 1; 213 goto Exit; 214 case VtQHello: 215 if(!dispatchHello(z, &p)) 216 goto Exit; 217 break; 218 case VtQRead: 219 if(!dispatchRead(z, &p)) 220 goto Exit; 221 break; 222 case VtQWrite: 223 if(!dispatchWrite(z, &p)) 224 goto Exit; 225 break; 226 case VtQSync: 227 if(!dispatchSync(z, &p)) 228 goto Exit; 229 break; 230 } 231 if(p != nil) { 232 hdr = packetHeader(p, 2); 233 hdr[0] = op+1; 234 hdr[1] = tid; 235 } else { 236 p = packetAlloc(); 237 hdr = packetHeader(p, 2); 238 hdr[0] = VtRError; 239 hdr[1] = tid; 240 if(!vtAddString(p, vtGetError())) 241 goto Exit; 242 } 243 244 vtDebug(z, "server send: "); 245 vtDebugMesg(z, p, "\n"); 246 247 if(!vtSendPacket(z, p)) { 248 p = nil; 249 goto Exit; 250 } 251 } 252 Exit: 253 if(p != nil) 254 packetFree(p); 255 if(z->vtbl->closing) 256 z->vtbl->closing(z, clean); 257 vtClose(z); 258 vtFree(z); 259 vtDetach(); 260 261 exits(0); 262 return 0; /* never gets here */ 263 } 264 265