001 #exe {Cd(__DIR__);};; 002 #include "MainDrawer.HC"; 003 U0 PrintI(U8 *s,I64 l) { 004 DbgPrint("%s:%d\n",s,l); 005 } 006 #define GAME_LIST_PORT 7000 007 008 class CListClient:CQue { 009 I64 socket; 010 I64 host_game_at_port; 011 I64 connected; //This will close da connection 012 U8 host_game_wad[STR_LEN]; 013 U8 host_game_desc[STR_LEN]; 014 }; 015 U0 SendString(I64 sock,U8 *fmt,...) { 016 U32 l; 017 fmt=StrPrintJoin(NULL,fmt,argc,argv); 018 l=StrLen(fmt); 019 send(sock,&l,4,0); 020 send(sock,fmt,l,0); 021 Free(fmt); 022 } 023 U8 *ReceiveString(I64 sock) { 024 U32 len; 025 I64 h=recv(sock,&len,4,0); 026 if(4!=h) 027 return NULL; 028 U8 *ret=CAlloc(len+1); 029 I64 got=recv(sock,ret,len,0); 030 if(len!=got) { 031 Free(ret); 032 return NULL; 033 } 034 return ret; 035 } 036 U0 ServerIncomingTask(CListClient *cl) { 037 U32 len; 038 I64 host_at,wad_hash; 039 U8 *body,*_body,*tmp; 040 U8 command[STR_LEN],*ptr,*ptr2; 041 CListClient *clients=FramePtr("Clients"),*client; 042 while(_body=ReceiveString(cl->socket)) { 043 body=_body; 044 ptr=command; 045 body=StrScan(body,"%s:",&ptr); 046 if(!StrCmp(command,"LIST")) { 047 for(client=clients->next;client!=clients;client=client->next) { 048 if(client->host_game_wad[0]&&client->host_game_at_port) { 049 SendString(cl->socket,"GAME:%s(%s):%d\n", 050 client->host_game_wad, 051 client->host_game_desc, 052 client->host_game_at_port); 053 } 054 } 055 SendString(cl->socket,"DONE:"); 056 } else if(!StrCmp(command,"HOST")) { 057 ptr=&cl->host_game_wad; 058 ptr2=&cl->host_game_desc; 059 body=StrScan(body,"%s(%s):%d\n",&ptr,&ptr2,&wad_hash); 060 tmp=MStrPrint(" RemoveHost(0x%X\n);\n",cl); 061 FramePtrAdd("SLIM_PROX_EXIT_CB",tmp); 062 SlimProxServerTask(cl->socket,&cl->host_game_at_port); 063 Free(_body); 064 return; 065 } 066 Free(_body); 067 } 068 QueRem(cl); 069 close(cl->socket); 070 Free(cl); 071 } 072 U0 ServerTaskEnd() { 073 CListClient *clients=FramePtr("Clients"),*client; 074 for(client=clients->next;client!=clients;client=client->next) { 075 close(client->socket); 076 } 077 QueDel(clients); 078 Free(clients); 079 close(FramePtr("ListenSock")); 080 Exit; 081 } 082 U0 ServerTask(U8 *at="0.0.0.0") { 083 I64 listen_sock=create_server("0.0.0.0",GAME_LIST_PORT,21 /* Savage */ ); 084 I64 who; 085 CListClient *clients=CAlloc(sizeof CQue),*poo; 086 QueInit(clients); 087 FramePtrAdd("ListenSock",listen_sock); 088 FramePtrAdd("Clients",clients); 089 Fs->task_end_cb=&ServerTaskEnd; 090 while(who=accept(listen_sock,NULL,0)) { 091 if(who>0) { 092 poo=CAlloc(sizeof CListClient); 093 poo->socket=who; 094 QueIns(poo,clients); 095 Spawn(&ServerIncomingTask,poo,,,Fs); 096 } 097 Sleep(3); 098 } 099 } 100 U0 HostGameBrowser(U8 *at="0.0.0.0") { 101 CTask *t=Spawn(&ServerTask,at,,,Fs); 102 "Press a key to stop serving\n"; 103 PressAKey; 104 Kill(t,FALSE); 105 } 106 class CHostGameData { 107 U8 game_wad[STR_LEN] format "$DA-P,A=\"DoomWad :%s\"$\n"; 108 U8 game_pwad[STR_LEN] format "$DA-P,A=\"PWad :%s\"$\n"; 109 U8 name[STR_LEN] format "$DA-P,A=\"Name :%s\"$\n"; 110 U8 desc[STR_LEN] format "$DA-P,A=\"Desciption :%s\"$\n"; 111 Bool just_serve format "$CB,\"Just Serve:\"$\n"; 112 I64 wad_hash; 113 }; 114 U0 RemoveHost(CListClient *cl) { 115 QueRem(cl); 116 Free(cl); 117 } 118 U0 HostGame(I64 sock) { 119 CHostGameData data; 120 CTask *me; 121 U8 *map,*tmp; 122 if(!FramePtr("USE_WAD")) { 123 PopUpOk("Can't find a Doom WAD to use!!\n"); 124 throw('Wad'); 125 } 126 StrCpy(&data.game_wad,FramePtr("USE_WAD")); 127 StrCpy(&data.name,"Untitled"); 128 StrCpy(&data.desc,""); 129 StrCpy(&data.game_pwad,""); 130 data.just_serve=FALSE; 131 data.wad_hash=0; 132 DocForm(&data,,0,"$PURPLE$$TX+C,\"Host a game of Doom.\"$$FD$\n"); 133 SendString(sock,"HOST:%s:%s(%s):%d\n",data.game_wad,data.game_pwad,data.name,data.wad_hash); 134 if(W_GetLumpPtrFromName("E1M1")) { 135 map="E1M1"; 136 } else if(W_GetLumpPtrFromName("MAP01")) { 137 map="MAP01"; 138 } else { 139 PopUpOk("I can't find the first level!!!\n"); 140 throw('Wad'); 141 } 142 FramePtrAdd("SLIM_PROX",1); 143 FramePtrAdd("SLIM_PROX_SOCK",sock); 144 if(!data.just_serve) { 145 me=User; 146 FramePtrAdd("SLIM_PROX",1,me); 147 FramePtrAdd("SLIM_PROX_USE_DUMB_SOCK",1,me); 148 WinMax(me); 149 XTalk(me,"#include \"%Q/MPClient\";;\n",__DIR__); 150 } 151 //See SlimProx.HC 152 PrintI(" serce",1); 153 ServeGame(map ,4); 154 Beep; 155 close(sock); 156 } 157 U0 DeleteBranch(CDoc *doc,U8 *who) { 158 CDocEntry *br,*st,*en; 159 if(DocTreeFind(doc,who,&br,&st,&en)) { 160 DocCut(doc,br,en); 161 } 162 } 163 //Returns server port 164 I64 ServerBrowser(U8 *server="0.0.0.0") { 165 F64 next_refresh_tS=0; 166 CI64Set *games=I64SetNew; 167 CI64Set *old_games=I64SetNew; 168 CDoc *doc=DocPut; 169 Bool continue=TRUE; 170 I64 msg,m1,m2,idx; 171 I64 listen_sock=create_connection(server,GAME_LIST_PORT); 172 U8 *buf,*_buf; 173 U8 wad[STR_LEN],*ptr,*wad_ptr=wad; 174 U8 pwad[STR_LEN],*pwad_ptr=pwad; 175 U8 desc[STR_LEN],*ptr2,*desc_ptr=desc; 176 I64 port,has_action; 177 DocClear; 178 DocPrint(doc,"$LTPURPLE$$TX+C+H,\"Listing of %Q\"$$FD$\n",server); 179 DocPrint(doc,"\n\n$BT+H+PU,\"Host game\",LM=\"HostGame(%d);\\n\"\n\n$",listen_sock); 180 while(continue) { 181 if(next_refresh_tS<tS) { 182 next_refresh_tS=tS+1.; 183 SendString(listen_sock,"LIST:"); 184 old_games->cnt=0; 185 for(idx=0;idx!=games->cnt;idx++) { 186 I64SetAdd(old_games,games->body[idx]); 187 } 188 games->cnt=0; 189 while(buf=ReceiveString(listen_sock)) { 190 _buf=buf; 191 if(!StrNCmp("GAME:",_buf,5)) { 192 buf+=5; 193 ptr=StrNew(buf); 194 for(idx=0;idx!=old_games->cnt;idx++) { 195 if(!StrCmp(ptr,ptr2=old_games->body[idx])) { 196 I64SetRem(old_games,ptr2); 197 Free(ptr2); 198 I64SetAdd(games,ptr); 199 goto skip; 200 } 201 } 202 I64SetAdd(games,ptr); 203 StrScan(buf,"%s:%s(%s):%d\n",&wad_ptr,&pwad_ptr,&desc_ptr,&port); 204 if(!*pwad_ptr) 205 ptr=MStrPrint("%Q:%d/%Q",wad,port,desc); 206 else 207 ptr=MStrPrint("%Q(%Q):%d/%Q",wad,pwad,port,desc); 208 209 if(!DocTreeFind(doc,ptr)) { 210 DocTreeWrite(doc,ptr,FALSE,"\n\n$BT,\"Join Game\",LM=\"PlayNetworkGame(\\\"%Q\\\",%d);\n;\"$\n\n",server,port); 211 DocCollapse(FALSE,doc); 212 } 213 Free(ptr); 214 skip: 215 } else if(!StrNCmp("DONE:",_buf,5)) { 216 for(idx=0;idx!=old_games->cnt;idx++) { 217 ptr=old_games->body[idx]; 218 StrScan(ptr,"%s:%s(%s):%d\n",&wad_ptr,&pwad_ptr,&desc_ptr,&port); 219 if(!*pwad_ptr) 220 ptr2=MStrPrint("%Q:%d/%Q",wad,port,desc); 221 else 222 ptr2=MStrPrint("%Q(%Q):%d/%Q",wad,pwad,port,desc); 223 DeleteBranch(doc,ptr2); 224 Free(ptr2); 225 Free(ptr); 226 } 227 old_games->cnt=0; 228 Free(_buf); 229 break; 230 } 231 Free(_buf); 232 } 233 } 234 if(MSG_KEY_DOWN==ScanMsg(&m1,&m2)) { 235 if(m1==' '||m1=='\n'||m1==CH_ESC) { 236 DocEntryRun(doc,doc->cur_entry,FALSE,&has_action); 237 if(has_action||m1==CH_ESC) { 238 break; 239 } 240 } 241 DocPutKey(doc,m1,m2); 242 } 243 Refresh; 244 } 245 m1=games->cnt; 246 while(--m1>=0) 247 Free(games->body[m1]); 248 I64SetDel(games); 249 } 250 #if __CMD_LINE__ 251 ServerBrowser("aiwnios.com"); 252 //ServerBrowser("0.0.0.0"); 253 #endif