001 #exe {Cd(__DIR__);};; 002 #include "Generic.HC"; 003 #include "Set.HC"; 004 class CNetAddr { 005 U8 *hostname; 006 I64 port; 007 }; 008 class CExodusSock:CSocket { 009 I64 sock_num; 010 CI64Set *children; 011 I64 read_cnt,write_cnt,hangup_cnt; 012 U8 *read_base; //Free this 013 U8 *write_ptr,*read_ptr; 014 }; 015 CTask *net_task=NULL; 016 CDyadStream *dyad_socks[0x10000]; 017 CExodusSock *exodus_socks[0x10000]; 018 extern CExodusSock *_Socket(CDyadStream *stream); 019 U0 DyadSocketTaskEnd() { 020 DyadShutdown; 021 Exit; 022 } 023 U0 DyadSocketTask(I64 s) { 024 DyadInit; 025 net_task=Fs; 026 Fs->task_end_cb=&DyadSocketTaskEnd; 027 MemSetI64(dyad_socks,0,0x10000); 028 MemSetI64(exodus_socks,0,0x10000); 029 while(TRUE) { 030 DyadUpdate; 031 Sleep(10); 032 } 033 } 034 I64 FindFreeSock() { 035 I64 i=0; 036 for(i=0;i!=0x10000;i++) 037 if(!dyad_socks[i]) 038 return i; 039 return -1; 040 } 041 I64 DyadSockIdx(CDyadStream *s) { 042 I64 i=0; 043 for(i=0;i!=0x10000;i++) { 044 if(dyad_socks[i]==s) 045 return i; 046 } 047 return -1; 048 } 049 I64 ExodusGetAddrInfo(U8 *node,U8*ul,addrinfo *hints=NULL,addrinfo **res) { 050 sockaddr_in *addr=CAlloc(sizeof sockaddr_in); 051 addrinfo *info=CAlloc(sizeof addrinfo); 052 CNetAddr *new=CAlloc(sizeof CNetAddr); 053 new->hostname=StrNew(node); 054 new->port=0; 055 info->ai_family=AF_INET; 056 info->ai_canonname=StrNew(node); 057 info->ai_addr=addr; 058 info->ai_socktype=SOCK_STREAM; 059 addr->sin_zero[0](U64*)=new; 060 *res=info; 061 return 0; 062 } 063 064 socket_addr_resolver=CAlloc(sizeof CAddrResolver); 065 socket_addr_resolver->getaddrinfo=&ExodusGetAddrInfo; 066 I64 ExodusAccept(CExodusSock *_s,sockaddr *src_addr,I64 addr_len) { 067 I64 s=_s->sock_num; 068 I64 code; 069 CExodusSock *got; 070 if(_s->read_cnt) { 071 _s->read_cnt--; 072 got=_s->children->body[0]; 073 I64SetRem(_s->children,got); 074 } else 075 got=-1; 076 return got; 077 } 078 I64 ExodusClose(CExodusSock *_s) { 079 CDyadStream *ds=dyad_socks[_s->sock_num]; 080 dyad_socks[_s->sock_num]=NULL; 081 exodus_socks[_s->sock_num]=NULL; 082 DyadEnd(ds); 083 Free(_s); 084 return 0; 085 } 086 I64 ExodusBind(CExodusSock *_s,sockaddr_in *src_addr,I64 addr_len) { 087 CNetAddr *from=src_addr->sin_zero[0](U64*); 088 DyadListen(dyad_socks[_s->sock_num],htons(src_addr->sin_port),from->hostname); 089 return 0; 090 } 091 I64 ExodusConnect(CExodusSock *_s,sockaddr_in *src_addr,I64 addr_len) { 092 CNetAddr *from=src_addr->sin_zero[0](U64*); 093 //Use port from src_addr 094 DyadConnect(dyad_socks[_s->sock_num],from->hostname,htons(src_addr->sin_port)); 095 return 0; 096 } 097 I64 ExodusListen(CExodusSock *_s,I64 backlog) { 098 //See NetBind 099 return 0; 100 } 101 I64 ExodusRecvFrom(CExodusSock *_s,U8 *buf,I64 len,I64 flags,sockaddr *ul,I64 addrlen) { 102 //TODO wherefrom 103 ent:; 104 I64 s=_s->sock_num; 105 I64 buf_len=_s->write_ptr-_s->read_ptr; 106 if(!buf_len) {Sleep(4);goto ent;} 107 if(buf_len>=len) { 108 MemCpy(buf,_s->read_ptr,len); 109 _s->read_ptr+=len; 110 return len; 111 } 112 MemCpy(buf,_s->read_ptr,buf_len); 113 _s->read_ptr+=buf_len; 114 return buf_len; 115 } 116 I64 ExodusSendTo(CExodusSock* _s, U8* buf, I64 len, I64 flags, sockaddr* dest_addr, I64 addrlen) { 117 //TODO whereto 118 I64 s=_s->sock_num; 119 DyadWrite(dyad_socks[s],buf,len); 120 return len; 121 122 } 123 I64 ExodusSockOpt(CExodusSock* _s, I64 level, I64 optname, U8* optval, I64 optlen) { 124 //Poop taods 125 } 126 static U0 DyadReadCallback(CDyadStream *who,U8 *buf,I64 len,U8 *ud) { 127 CExodusSock *s=ud; 128 I64 buf_len; 129 U8 *copy; 130 buf_len=s->write_ptr-s->read_base; 131 if(!s->read_base) { 132 s->read_base=CAlloc(len+32); 133 s->read_ptr=s->read_base; 134 s->write_ptr=s->read_base; 135 } else if(buf_len+len>=MSize(s->read_base)) { 136 buf_len=s->write_ptr-s->read_ptr; 137 copy=s->read_base; 138 s->read_base=CAlloc(len+32+buf_len); 139 MemCpy(s->read_base,s->read_ptr,buf_len); 140 Free(copy); 141 s->read_ptr=s->read_base; 142 s->write_ptr=s->read_base+buf_len; 143 } 144 MemCpy(s->write_ptr,buf,len); 145 s->write_ptr+=len; 146 } 147 static U0 DyadAcceptCallback(CDyadStream *new,CExodusSock *s) { 148 I64SetAdd(s->children,_Socket(new)); 149 s->read_cnt++; 150 } 151 static U0 DyadCloseCallback(CDyadStream *who,U8 *user_data) { 152 I64 idx=DyadSockIdx(who); 153 if(idx==-1) return; 154 CExodusSock *s=exodus_socks[idx]; 155 s->hangup_cnt++; 156 } 157 CExodusSock *_Socket(CDyadStream *stream) { 158 CExodusSock *ret=CAlloc(sizeof CExodusSock); 159 I64 sock=FindFreeSock; 160 ret->sock_num=sock; 161 ret->accept=&ExodusAccept; 162 ret->bind=&ExodusBind; 163 ret->close=&ExodusClose; 164 ret->connect=&ExodusConnect; 165 ret->listen=&ExodusListen; 166 ret->recvfrom=&ExodusRecvFrom; 167 ret->sendto=&ExodusSendTo; 168 ret->setsockopt=&ExodusSockOpt; 169 ret->children=I64SetNew; 170 DyadSetListenCallback(stream,DYAD_EVENT_ACCEPT,&DyadAcceptCallback,ret); 171 DyadSetReadCallback(stream,DYAD_EVENT_DATA,&DyadReadCallback,ret); 172 DyadSetCloseCallback(stream,DYAD_EVENT_CLOSE,&DyadCloseCallback,ret); 173 dyad_socks[sock]=stream; 174 exodus_socks[sock]=ret; 175 return ret; 176 } 177 178 U8 *ExodusSocket(U16,U16) { 179 if(!net_task) { 180 Spawn(&DyadSocketTask,0,"DyadShim",-1,Fs); 181 while(!net_task) 182 Yield; 183 } 184 return _Socket(DyadNewStream); 185 } 186 187 RegisterSocketClass(AF_INET,SOCK_STREAM,&ExodusSocket); 188 189 /*I64 sock=create_connection("aiwnios.com",6667); 190 sendString(sock, 191 "NICK asshole\n" 192 "USER asshole 0 * :asshole\n" 193 ,0); 194 U8 buf[STR_LEN]; 195 recvLine(sock,buf,STR_LEN,0); 196 "%s\n",buf; 197 sendString(sock, 198 "JOIN #main\n" 199 ,0); 200 while(recvLine(sock,buf,STR_LEN,0)) 201 "%s\n",buf; 202 close(sock);*/