001 #exe {FramePtrAdd("OLD_DIR",__DIR__);Cd(__DIR__);}; 002 #exe { // useful for dynamic includes, eg CrossNetShims 003 Bool a,e; 004 Bool _FindDef(U8 *nam,U8 *fmt,...) { 005 Bool ret; 006 U8 *s=StrPrintJoin(NULL,fmt,argc,argv); 007 if (ret=!!HashFind(nam,Fs->hash_table,HTT_DEFINE_STR)) 008 StreamPrint("%s;;\n",s); 009 Free(s); 010 return ret; 011 } 012 a=_FindDef("__AIWNIOS__","\"Running on Aiwnios\\n\";\n"); 013 e=_FindDef("__EXODUS","\"Running on Exodus\\n\";\n"); 014 if (!a && !e) { 015 StreamPrint("\"Possibly stock TempleOS\\n\";\n"); 016 StreamPrint("#include \"CrossNetShims/Generic.HC\";;\n"); 017 } else if(a) { 018 StreamPrint("#include \"CrossNetShims/Aiwnios2.HC\";;\n"); 019 } else if(e) { 020 StreamPrint("#include \"CrossNetShims/EXODUS.HC\";;\n"); 021 } 022 };; 023 #exe{ 024 Cd(FramePtr("OLD_DIR")); 025 FramePtrDel("OLD_DIR"); 026 } 027 I64 ForceSend(I64 sock,U8 *buf,I64 len,U64 ul=0) { 028 I64 sent; 029 I64 olen=len; 030 while(len>0) { 031 sent=send(sock,buf,len,ul); 032 if(sent<0) { 033 return -1; 034 } 035 buf+=sent; 036 len-=sent; 037 if(len) 038 Yield; 039 } 040 return olen; 041 } 042 I64 ForceRecv(I64 sock,U8 *buf,I64 len,U64 ul=0) { 043 I64 got; 044 I64 olen=len; 045 while(len>0) { 046 got=recv(sock,buf,len,ul); 047 if(got<0) { 048 return -1; 049 } 050 buf+=got; 051 len-=got; 052 if(len) 053 Yield; 054 } 055 return olen; 056 } 057 CTask *slim_prox_task=Fs; 058 class CSlimProxSock { 059 I64 proxy,lock; 060 CSlimProxSock *parent; 061 union { 062 CFifoU8 *read_fifo; 063 CFifoI64 *accept_fifo; 064 }; 065 CFifoU8 *write_fifo; 066 CI64Set *children; 067 Bool closed; 068 //is_dumb is for SlimProxDumbCreateConnection() 069 Bool is_dumb; 070 }; 071 #define SLIM_PROX_WRITE 1 072 #define SLIM_PROX_ACCEPT 2 073 #define SLIM_PROX_DISCONNECT 3 074 I64 class CSlimProxHeader { 075 U8 ident; 076 U8 pad; 077 U16 who; 078 U32 size; 079 }; 080 U0 SlimProxTaskRead(CSlimProxSock *root_sock) { 081 CSlimProxHeader hdr; 082 CSlimProxSock **socks,*who; 083 I64 cnt=0,got; 084 U8 buf[0x20000],*ptr; 085 while(TRUE) { 086 got=ForceRecv(root_sock->proxy,&hdr,sizeof(CSlimProxHeader),0); 087 if(sizeof(CSlimProxHeader)==got) { 088 cnt=hdr.size; 089 switch(hdr.ident) { 090 case SLIM_PROX_DISCONNECT: { 091 if(hdr.who<root_sock->children->cnt) { 092 who=root_sock->children->body[hdr.who]; 093 if(who) { 094 who->closed=TRUE; 095 } 096 } 097 } 098 break; 099 case SLIM_PROX_ACCEPT: { 100 who=CAlloc(sizeof(CSlimProxSock),Fs->parent_task); 101 if(FifoI64Ins(root_sock->accept_fifo,who)) { 102 who->parent=root_sock; 103 who->children=I64SetNew(); 104 who->write_fifo=FifoU8New(1<<20,Fs->parent_task); 105 who->read_fifo=FifoU8New(1<<20,Fs->parent_task); 106 I64SetAdd(root_sock->children,who); 107 } else { 108 Free(who); 109 } 110 } 111 break; 112 case SLIM_PROX_WRITE: { 113 if(hdr.who<root_sock->children->cnt) { 114 who=root_sock->children->body[hdr.who]; 115 if(who) 116 while(cnt>0) { 117 got=ForceRecv(root_sock->proxy,buf,MinI64(cnt,0x20000),0); 118 if(got<=0) 119 goto fin; 120 if(got>0) 121 cnt-=got; 122 ptr=buf; 123 while(--got>=0) { 124 while(!FifoU8Ins(who->read_fifo,*ptr)) 125 Sleep(1); 126 ++ptr; 127 } 128 } 129 } 130 } 131 break; 132 default: 133 goto fin; 134 break; 135 } 136 } else 137 break; 138 } 139 fin:; 140 if(ptr=FramePtr("SLIM_PROX_EXIT_CB")) { 141 ExePutS(ptr); 142 } 143 } 144 U0 SlimProxTaskWrite(CSlimProxSock *root_sock) { 145 I64 cnt=0; 146 CSlimProxSock **socks; 147 U8 buf[0x20000],*ptr; 148 CSlimProxHeader hdr; 149 while(TRUE) { 150 again: 151 if(root_sock->children) { 152 cnt=root_sock->children->cnt; 153 socks=root_sock->children->body; 154 while(--cnt>=0) { 155 if(!socks[cnt]->closed&&!socks[cnt]->is_dumb) { 156 ptr=buf; 157 while(FifoU8Rem(socks[cnt]->write_fifo,ptr)) { 158 ptr++; 159 } 160 if(ptr!=&buf) { 161 hdr.ident=SLIM_PROX_WRITE; 162 hdr.who=cnt; 163 hdr.size=ToI64(ptr)-ToI64(&buf); 164 ForceSend(root_sock->proxy,&hdr,sizeof(CSlimProxHeader),0); 165 ForceSend(root_sock->proxy,buf,hdr.size,0); 166 } 167 } 168 } 169 } 170 Sleep(1); 171 } 172 } 173 174 I64 SlimProxDumbCreateConnection() { 175 again:; 176 CSlimProxSock *root_sock=FramePtr("DUMB_SLIM_PROX_ROOT",adam_task),*who; 177 if(!root_sock) { 178 Sleep(1); 179 goto again; 180 } 181 FramePtrAdd("SLIM_PROX",1); 182 FramePtrAdd("SLIM_PROX_IS_DUMB",1); 183 who=CAlloc(sizeof(CSlimProxSock)); 184 who->is_dumb=TRUE; 185 who->parent=root_sock; 186 who->children=I64SetNew(); 187 who->write_fifo=FifoU8New(1<<20,Fs->parent_task); 188 who->read_fifo=FifoU8New(1<<20,Fs->parent_task); 189 I64SetAdd(root_sock->children,who); 190 FifoI64Ins(root_sock->accept_fifo,who); 191 return who; 192 } 193 194 195 196 CSlimProxSock *SlimProxCreateConnection(U8 *at,I64 port) { 197 if(FramePtr("SLIM_PROX_USE_DUMB_SOCK")) 198 return SlimProxDumbCreateConnection; 199 if(FramePtr("SLIM_PROX")) { 200 "Only servers use slim-proxy,clients connect throug tha main server.\n"; 201 throw('AssPony'); 202 } 203 return create_connection(at,port); 204 } 205 U0 ServerCleanup() { 206 FramePtrDel("DUMB_SLIM_PROX_ROOT",adam_task); 207 Exit; 208 } 209 CSlimProxSock *SlimProxCreateServer(U8 *at,I64 port,I64 bl) { 210 if(!FramePtr("SLIM_PROX")) 211 return create_server(at,port,bl); 212 if(!FramePtr("SLIM_PROX_SOCK")) 213 throw('SlimProx'); 214 CSlimProxSock *root_sock=CAlloc(sizeof CSlimProxSock); 215 root_sock->proxy=FramePtr("SLIM_PROX_SOCK"); 216 root_sock->children=I64SetNew(); 217 root_sock->accept_fifo=FifoI64New(0x10,Fs->parent_task); 218 root_sock->write_fifo=FifoU8New(0x10,Fs->parent_task); 219 Spawn(&SlimProxTaskRead,root_sock,,,Fs); 220 Spawn(&SlimProxTaskWrite,root_sock,,,Fs); 221 FramePtrAdd("DUMB_SLIM_PROX_ROOT",root_sock,adam_task); 222 Fs->task_end_cb=&ServerCleanup; 223 return root_sock; 224 } 225 226 227 #define SLIM_PROX_START_PORT 7001 228 #define SLIM_PROX_END_PORT 7100 229 U8 used_ports[SLIM_PROX_END_PORT-SLIM_PROX_START_PORT+1]; 230 MemSet(used_ports,FALSE,SLIM_PROX_END_PORT-SLIM_PROX_START_PORT+1); 231 232 233 234 235 U0 SlimProxServerReadTask(I64 sock) { 236 I64 who=FramePtr("ToSock"); 237 I64 new,idx; 238 I64 *avail=FramePtr("AvailSocks"); 239 CArcCompress head,*load; 240 CSlimProxHeader hdr; 241 for(idx=0;idx!=0x10;idx++) 242 if(avail[idx]==sock) 243 break; 244 while(sizeof(CArcCompress)==ForceRecv(sock,&head,sizeof(CArcCompress),0)) { 245 if(head.compressed_size<1<<20) { 246 load=CAlloc(head.compressed_size); 247 MemCpy(load,&head,sizeof CArcCompress); 248 if(0>ForceRecv(sock,load+1,head.compressed_size-sizeof(CArcCompress),0)) { 249 Free(load); 250 break; 251 } 252 } else 253 break; 254 hdr.ident=SLIM_PROX_WRITE; 255 hdr.size=load->compressed_size; 256 hdr.who=idx; 257 ForceSend(who,&hdr,sizeof(CSlimProxHeader),0); 258 ForceSend(who,load,load->compressed_size,0); 259 Free(load); 260 } 261 hdr.ident=SLIM_PROX_DISCONNECT; 262 hdr.size=0; 263 hdr.who=idx; 264 ForceSend(who,&hdr,sizeof(CSlimProxHeader),0); 265 close(sock); 266 } 267 268 U0 SlimProxServerAcceptTask(I64) { 269 I64 who=FramePtr("ToSock"); 270 I64 server=FramePtr("ServerSock"); 271 I64 new,idx; 272 I64 *avail=FramePtr("AvailSocks"); 273 U8 *tmp; 274 CSlimProxHeader hdr; 275 while(new=accept(server,NULL,0)) { 276 if(new==-1) 277 break; 278 for(idx=0;idx!=0x10;idx++) { 279 if(!avail[idx]) { 280 avail[idx]=new; 281 hdr.ident=SLIM_PROX_ACCEPT; 282 hdr.size=0; 283 hdr.who=idx; 284 ForceSend(who,&hdr,sizeof(CSlimProxHeader),0); 285 Spawn(&SlimProxServerReadTask,new,,,Fs); 286 goto next; 287 } 288 } 289 //Not enough open holes 290 close(new); 291 next:; 292 } 293 if(tmp=FramePtr("SLIM_PROX_EXIT_CB")) { 294 ExePutS(tmp); 295 } 296 close(server); 297 298 } 299 U0 SlimProxServerTask(I64 sock,I64 *port=NULL) { 300 //No need to lock as we are 21 Savage runnin' on core 0 301 I64 use_port=SLIM_PROX_START_PORT; 302 I64 server_sock,cnt; 303 I64 avail_socks[0x10]; 304 CSlimProxHeader hdr; 305 U8 buf[0x10000*2],*tmp; 306 MemSetI64(avail_socks,NULL,0x10); 307 while(use_port<SLIM_PROX_END_PORT) { 308 if(!used_ports[use_port]) 309 break; 310 use_port++; 311 } 312 //No availbe ports 313 if(use_port==SLIM_PROX_END_PORT) { 314 fail:; 315 close(sock); 316 return; 317 } 318 server_sock=create_server("0.0.0.0",use_port,0x10); 319 if(port) *port=use_port; 320 FramePtrAdd("ServerSock",server_sock); 321 FramePtrAdd("ToSock",sock); 322 FramePtrAdd("AvailSocks",avail_socks); 323 if(server_sock<=0) 324 goto fail; 325 Spawn(&SlimProxServerAcceptTask,0,,,Fs); 326 while(TRUE) { 327 cnt=ForceRecv(sock,&hdr,sizeof(CSlimProxHeader),0); 328 if(cnt<0) { 329 break; 330 } 331 if(hdr.ident==SLIM_PROX_WRITE) { 332 if(avail_socks[hdr.who]) { 333 while(hdr.size>0) { 334 cnt=ForceRecv(sock,&buf,MinI64(hdr.size,0x10000*2),0); 335 if(cnt) ForceSend(avail_socks[hdr.who],buf,cnt,0); 336 hdr.size-=cnt; 337 } 338 } 339 } else if(hdr.ident==SLIM_PROX_DISCONNECT) { 340 if(cnt=avail_socks[hdr.who]) 341 close(cnt); 342 if(0<=hdr.who<0x10) 343 avail_socks[hdr.who]=NULL; 344 } 345 Sleep(1); 346 } 347 if(tmp=FramePtr("SLIM_PROX_EXIT_CB")) { 348 ExePutS(tmp); 349 } 350 Beep(10); 351 close(server_sock); 352 close(sock); 353 } 354 U0 SlimProxClose(I64 sock) { 355 if(!FramePtr("SLIM_PROX")) { 356 close(sock); 357 } else { 358 CSlimProxSock *sp=sock,*p; 359 if(p=sp->parent) { 360 I64SetRem(p->children,p); 361 } 362 sp->closed=TRUE; 363 } 364 } 365 I64 SlimProxAccept(I64 sock,U8 *who,I64 ul) { 366 if(!FramePtr("SLIM_PROX")) 367 return accept(sock,who,ul); 368 CSlimProxSock *sp=sock,ret; 369 if(sp->closed) return -1; 370 while(!FifoI64Cnt(sp->accept_fifo)) { 371 if(sp->closed) return -1; 372 Sleep(1); 373 } 374 FifoI64Rem(sp->accept_fifo,&ret); 375 return ret; 376 } 377 378 I64 SlimProxReceive(I64 sock,U8 *buf,I64 len,I64 ul) { 379 if(!FramePtr("SLIM_PROX")) 380 return ForceRecv(sock,buf,len,ul); 381 I64 ate; 382 CSlimProxSock *sp=sock; 383 CFifoU8 *use_fifo; 384 if(sp->closed) return -1; 385 //Swap read/write for "DUMB" 386 if(FramePtr("SLIM_PROX_IS_DUMB")) { 387 use_fifo=sp->write_fifo; 388 } else 389 use_fifo=sp->read_fifo; 390 while(FifoU8Cnt(use_fifo)<len) { 391 if(sp->closed) { 392 return -1; 393 } 394 Sleep(1); 395 } 396 U8 *o=buf; 397 ate=len; 398 while(--len>=0) 399 FifoU8Rem(use_fifo,buf++); 400 return ate; 401 } 402 I64 SlimProxSend(I64 sock,U8 *buf,I64 len,I64 ul) { 403 I64 sent; 404 if(!FramePtr("SLIM_PROX")) { 405 ForceSend(sock,buf,len); 406 return len; 407 } 408 I64 ate=len; 409 CSlimProxSock *sp=sock; 410 CFifoU8 *use_fifo; 411 U8 *o=buf; 412 if(sp->closed) return -1; 413 while(LBts(&sp->lock,1)) 414 Yield; 415 //Swap read/write for "DUMB" 416 if(FramePtr("SLIM_PROX_IS_DUMB")) { 417 use_fifo=sp->read_fifo; 418 } else 419 use_fifo=sp->write_fifo; 420 while(--len>=0) { 421 while(!FifoU8Ins(use_fifo,*buf)) { 422 if(sp->closed) { 423 LBtr(&sp->lock,1); 424 return -1; 425 } 426 Sleep(1); 427 } 428 buf++; 429 } 430 LBtr(&sp->lock,1); 431 return ate; 432 }