static FILE *FetchFile(uint32 remlen) { #ifdef NETPLAY_ENABLED uint32 clen = remlen; char *cbuf; uLongf len; char *buf; FILE *fp; char *fn; if(clen > 500000) // Sanity check { NetError(); return(0); } //printf("Receiving file: %d...\n",clen); fn = FCEU_MakeFName(FCEUMKF_NPTEMP,0,0); if((fp = fopen(fn,"w+b"))) { cbuf = malloc(clen); if(!FCEUD_RecvData(cbuf, clen)) { NetError(); unlink(fn); fclose(fp); free(cbuf); free(fn); return(0); } len = FCEU_de32lsb(cbuf); if(len > 500000) // Another sanity check { NetError(); unlink(fn); fclose(fp); free(cbuf); free(fn); return(0); } buf = malloc(len); uncompress(buf, &len, cbuf + 4, clen - 4); fwrite(buf, 1, len, fp); free(buf); fseek(fp, 0, SEEK_SET); unlink(fn); free(fn); return(fp); } free(fn); #endif return(0); }
static FILE *FetchFile(uint32 remlen) { uint32 clen = remlen; char *cbuf; uLongf len; char *buf; FILE *fp; if(clen > 500000) // Sanity check { NetError(); return(0); } //printf("Receiving file: %d...\n",clen); if((fp = tmpfile())) { cbuf = (char *)FCEU_dmalloc(clen); //mbg merge 7/17/06 added cast if(!FCEUD_RecvData(cbuf, clen)) { NetError(); fclose(fp); free(cbuf); return(0); } len = FCEU_de32lsb((uint8*)cbuf); //mbg merge 7/17/06 added cast if(len > 500000) // Another sanity check { NetError(); fclose(fp); free(cbuf); return(0); } buf = (char *)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast uncompress((uint8*)buf, &len, (uint8*)cbuf + 4, clen - 4); //mbg merge 7/17/06 added casts fwrite(buf, 1, len, fp); free(buf); fseek(fp, 0, SEEK_SET); return(fp); } return(0); }
void MDFNI_NetplayQuit(const char *quit_message) { try { SendCommand(MDFNNPCMD_QUIT, strlen(quit_message), quit_message); } catch(std::exception &e) { NetError("%s", e.what()); } }
void FCEUI_NetplayText(uint8 *text) { uint32 len; len = strlen(text); if(!FCEUNET_SendCommand(FCEUNPCMD_TEXT,len)) return; if(!FCEUD_SendData(text,len)) NetError(); }
void FCEUI_NetplayText(uint8 *text) { uint32 len; len = strlen((char*)text); //mbg merge 7/17/06 added cast if(!FCEUNET_SendCommand(FCEUNPCMD_TEXT,len)) return; if(!FCEUD_SendData(text,len)) NetError(); }
void MDFNI_NetplayList(void) { try { SendCommand(MDFNNPCMD_REQUEST_LIST, 0); } catch(std::exception &e) { NetError("%s", e.what()); } }
void MDFNI_NetplayIntegrity(void) { try { SendCommand(MDFNNPCMD_INTEGRITY, 0); } catch(std::exception &e) { NetError("%s", e.what()); } }
void MDFNI_NetplayDupe(uint32 mask) { try { SendCommand(MDFNNPCMD_CTRLR_DUPE, mask); } catch(std::exception &e) { NetError("%s", e.what()); } }
void MDFNI_NetplaySwap(uint8 a, uint8 b) { try { SendCommand(MDFNNPCMD_CTRLR_SWAP, (a << 0) | (b << 8)); } catch(std::exception &e) { NetError("%s", e.what()); } }
void NetplaySendState(void) { try { SendState(); } catch(std::exception &e) { NetError("%s", e.what()); } }
bool NetplaySendCommand(uint8 cmd, uint32 len) { try { SendCommand(cmd, len); } catch(std::exception &e) { NetError("%s", e.what()); return(false); } return(true); }
void MDFNI_NetplayPing(void) { try { uint64 now_time; now_time = MDFND_GetTime(); // Endianness doesn't matter, since it will be echoed back only to us. SendCommand(MDFNNPCMD_ECHO, sizeof(now_time), &now_time); } catch(std::exception &e) { NetError("%s", e.what()); } }
int FCEUNET_SendCommand(uint8 cmd, uint32 len) { uint8 buf[numlocal + 1 + 4]; buf[0] = 0xFF; FCEU_en32lsb(&buf[numlocal], len); buf[numlocal + 4] = cmd; #ifdef NETWORK if(!FCEUD_SendData(buf,numlocal + 1 + 4)) { NetError(); return(0); } #endif return(1); }
void MDFNI_NetplayChangeNick(UTF8 *newnick) { try { uint32 len; if(!Joined) return; len = strlen((char *)newnick); SendCommand(MDFNNPCMD_SETNICK, len, newnick); } catch(std::exception &e) { NetError("%s", e.what()); } }
void MDFNI_NetplayText(const uint8 *text) { try { uint32 len; if(!Joined) return; len = strlen((char *)text); SendCommand(MDFNNPCMD_TEXT, len, text); } catch(std::exception &e) { NetError("%s", e.what()); } }
int FCEUNET_SendCommand(uint8 cmd, uint32 len) { //mbg merge 7/17/06 changed to alloca //uint8 buf[numlocal + 1 + 4]; uint8 *buf = (uint8*)alloca(numlocal+1+4); buf[0] = 0xFF; FCEU_en32lsb(&buf[numlocal], len); buf[numlocal + 4] = cmd; if(!FCEUD_SendData(buf,numlocal + 1 + 4)) { NetError(); return(0); } return(1); }
int FCEUNET_SendFile(uint8 cmd, char *fn) { #ifdef NETPLAY_ENABLED uint32 len; uLongf clen; char *buf, *cbuf; FILE *fp; struct stat sb; if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0); fstat(fileno(fp),&sb); len = sb.st_size; buf = malloc(len); fread(buf, 1, len, fp); fclose(fp); cbuf = malloc(4 + len + len / 1000 + 12); FCEU_en32lsb(cbuf, len); compress2(cbuf + 4, &clen, buf, len, 7); free(buf); //printf("Sending file: %s, %d, %d\n",fn,len,clen); len = clen + 4; #ifdef NETWORK if(!FCEUNET_SendCommand(cmd,len)) { free(cbuf); return(0); } if(!FCEUD_SendData(cbuf, len)) { NetError(); free(cbuf); return(0); } #endif free(cbuf); #endif return(1); }
int FCEUNET_SendFile(uint8 cmd, char *fn) { uint32 len; uLongf clen; char *buf, *cbuf; FILE *fp; struct stat sb; if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0); FCEUX_fstat(fileno(fp),&sb); len = sb.st_size; buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast fread(buf, 1, len, fp); fclose(fp); cbuf = (char*)FCEU_dmalloc(4 + len + len / 1000 + 12); //mbg merge 7/17/06 added cast FCEU_en32lsb((uint8*)cbuf, len); //mbg merge 7/17/06 added cast compress2((uint8*)cbuf + 4, &clen, (uint8*)buf, len, 7); //mbg merge 7/17/06 added casts free(buf); //printf("Sending file: %s, %d, %d\n",fn,len,clen); len = clen + 4; if(!FCEUNET_SendCommand(cmd,len)) { free(cbuf); return(0); } if(!FCEUD_SendData(cbuf, len)) { NetError(); free(cbuf); return(0); } free(cbuf); return(1); }
void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[], int NumPorts) { uint8 buf[TotalInputStateSize + 1]; try { // // // if(Joined) { uint8 outgoing_buffer[1 + LocalInputStateSize]; bool Taken[NumPorts]; memset(Taken, 0, sizeof(Taken)); outgoing_buffer[0] = 0; // This is not a command, duh! int wpos = 1; for(int x = 0; x < NumPorts; x++) { if(LocalPlayersMask & (1 << x)) { for(int n = 0; n <= x; n++) { if(!Taken[n] && !strcmp(PortDNames[n], PortDNames[x])) { memcpy(outgoing_buffer + wpos, PortData[n], PortLen[n]); Taken[n] = TRUE; wpos += PortLen[n]; break; } } } } MDFND_SendData(outgoing_buffer, 1 + LocalInputStateSize); } // // // uint8 cmd; uint32 cmd_raw_len; do { MDFND_RecvData(buf, TotalInputStateSize + 1); cmd = buf[TotalInputStateSize]; cmd_raw_len = MDFN_de32lsb(&buf[0]); if(cmd != 0) ProcessCommand(cmd, cmd_raw_len, PortDNames, PortData, PortLen, NumPorts); } while(cmd != 0); // // Update local port data buffers with data received. // { unsigned rpos = 0; for(int x = 0; x < NumPorts; x++) { memcpy(PortData[x], buf + rpos, PortLen[x]); rpos += PortLen[x]; } } } catch(std::exception &e) { NetError("%s", e.what()); } }
void NetplayUpdate(uint8 *joyp) { static uint8 buf[5]; /* 4 play states, + command/extra byte */ static uint8 joypb[4]; memcpy(joypb,joyp,4); /* This shouldn't happen, but just in case. 0xFF is used as a command escape elsewhere. */ if(joypb[0] == 0xFF) joypb[0] = 0xF; if(!netdcount) if(!FCEUD_SendData(joypb,numlocal)) { NetError(); return; } if(!netdcount) { do { if(!FCEUD_RecvData(buf,5)) { NetError(); return; } switch(buf[4]) { default: FCEU_DoSimpleCommand(buf[4]);break; case FCEUNPCMD_TEXT: { uint8 *tbuf; uint32 len = FCEU_de32lsb(buf); if(len > 100000) // Insanity check! { NetError(); return; } tbuf = (uint8*)malloc(len + 1); //mbg merge 7/17/06 added cast tbuf[len] = 0; if(!FCEUD_RecvData(tbuf, len)) { NetError(); free(tbuf); return; } FCEUD_NetplayText(tbuf); free(tbuf); } break; case FCEUNPCMD_SAVESTATE: { //mbg todo netplay //char *fn; //FILE *fp; ////Send the cheats first, then the save state, since ////there might be a frame or two in between the two sendfile ////commands on the server side. //fn = strdup(FCEU_MakeFName(FCEUMKF_CHEAT,0,0).c_str()); ////why?????? ////if(! // FCEUNET_SendFile(FCEUNPCMD_LOADCHEATS,fn); //// { //// free(fn); //// return; //// } //free(fn); //if(!FCEUnetplay) return; //fn = strdup(FCEU_MakeFName(FCEUMKF_NPTEMP,0,0).c_str()); //fp = fopen(fn, "wb"); //if(FCEUSS_SaveFP(fp,Z_BEST_COMPRESSION)) //{ // fclose(fp); // if(!FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn)) // { // unlink(fn); // free(fn); // return; // } // unlink(fn); // free(fn); //} //else //{ // fclose(fp); // FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy? Now!"); // unlink(fn); // free(fn); // return; //} } break; case FCEUNPCMD_LOADCHEATS: { FILE *fp = FetchFile(FCEU_de32lsb(buf)); if(!fp) return; FCEU_FlushGameCheats(0,1); FCEU_LoadGameCheats(fp); } break; //mbg 6/16/08 - netplay doesnt work right now anyway /*case FCEUNPCMD_LOADSTATE: { FILE *fp = FetchFile(FCEU_de32lsb(buf)); if(!fp) return; if(FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP)) { fclose(fp); FCEU_DispMessage("Remote state loaded.",0); } else FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy?"); } break;*/ } } while(buf[4]); netdcount=(netdcount+1)%netdivisor; memcpy(netjoy,buf,4); *(uint32 *)joyp=*(uint32 *)netjoy; } }
void NetplayUpdate(uint8 *joyp) { static uint8 buf[5]; /* 4 play states, + command/extra byte */ static uint8 joypb[4]; memcpy(joypb,joyp,4); /* This shouldn't happen, but just in case. 0xFF is used as a command escape elsewhere. */ if(joypb[0] == 0xFF) joypb[0] = 0xF; #ifdef NETWORK if(!netdcount) if(!FCEUD_SendData(joypb,numlocal)) { NetError(); return; } if(!netdcount) do { if(!FCEUD_RecvData(buf,5)) { NetError(); return; } switch(buf[4]) { default: FCEU_DoSimpleCommand(buf[4]);break; case FCEUNPCMD_TEXT: { uint8 *tbuf; uint32 len = FCEU_de32lsb(buf); if(len > 100000) // Insanity check! { NetError(); return; } tbuf = malloc(len + 1); tbuf[len] = 0; if(!FCEUD_RecvData(tbuf, len)) { NetError(); free(tbuf); return; } FCEUD_NetplayText(tbuf); free(tbuf); } break; case FCEUNPCMD_SAVESTATE: { char *fn; FILE *fp; /* Send the cheats first, then the save state, since there might be a frame or two in between the two sendfile commands on the server side. */ fn = FCEU_MakeFName(FCEUMKF_CHEAT,0,0); //if(! FCEUNET_SendFile(FCEUNPCMD_LOADCHEATS,fn); // { // free(fn); // return; // } free(fn); if(!FCEUnetplay) return; fn = FCEU_MakeFName(FCEUMKF_NPTEMP,0,0); fp = fopen(fn, "wb"); if(FCEUSS_SaveFP(fp)) { fclose(fp); if(!FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn)) { unlink(fn); free(fn); return; } unlink(fn); free(fn); } else { fclose(fp); FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy? Now!"); unlink(fn); free(fn); return; } } break; case FCEUNPCMD_LOADCHEATS: { FILE *fp = FetchFile(FCEU_de32lsb(buf)); if(!fp) return; FCEU_FlushGameCheats(0,1); FCEU_LoadGameCheats(fp); } break; case FCEUNPCMD_LOADSTATE: { FILE *fp = FetchFile(FCEU_de32lsb(buf)); if(!fp) return; if(FCEUSS_LoadFP(fp)) { fclose(fp); FCEU_DispMessage("Remote state loaded."); } else FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy?"); } break; } } while(buf[4]); #endif netdcount=(netdcount+1)%netdivisor; memcpy(netjoy,buf,4); *(uint32 *)joyp=*(uint32 *)netjoy; }
/** * @file * Tests for error classes. */ #include "catch.hpp" #include "../errors.hpp" SCENARIO("Errors contain a retrievable message", "[error]") { GIVEN("An Error") { Error e = NetError("need an RS-232 Interface Lead"); WHEN("Message() is called") { auto s = e.Message(); THEN("the result is the message given in the Error's ctor") { REQUIRE(s == "need an RS-232 Interface Lead"); } } } }
int NetplayStart(const char *PortDeviceCache[16], const uint32 PortDataLenCache[16]) { try { const char *emu_id = PACKAGE " " MEDNAFEN_VERSION; const uint32 local_players = MDFN_GetSettingUI("netplay.localplayers"); const std::string nickname = MDFN_GetSettingS("netplay.nick"); const std::string game_key = MDFN_GetSettingS("netplay.gamekey"); const std::string connect_password = MDFN_GetSettingS("netplay.password"); login_data_t *ld = NULL; std::vector<uint8> sendbuf; MDFNnetplay = true; sendbuf.resize(4 + sizeof(login_data_t) + nickname.size() + strlen(emu_id)); MDFN_en32lsb(&sendbuf[0], sendbuf.size() - 4); ld = (login_data_t*)&sendbuf[4]; if(game_key != "") { md5_context md5; uint8 md5out[16]; md5.starts(); md5.update(MDFNGameInfo->MD5, 16); md5.update((uint8 *)game_key.c_str(), game_key.size()); md5.finish(md5out); memcpy(ld->gameid, md5out, 16); } else memcpy(ld->gameid, MDFNGameInfo->MD5, 16); if(connect_password != "") { md5_context md5; uint8 md5out[16]; md5.starts(); md5.update((uint8*)connect_password.c_str(), connect_password.size()); md5.finish(md5out); memcpy(ld->password, md5out, 16); } assert(MDFNGameInfo->InputInfo->InputPorts <= 16); ld->protocol_version = 3; // Set input device number thingies here. ld->total_controllers = MDFNGameInfo->InputInfo->InputPorts; // Total number of ports MDFN_en32lsb(ld->emu_name_len, strlen(emu_id)); // Controller data sizes. for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++) ld->controller_data_size[x] = PortDataLenCache[x]; // Controller types for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++) { unsigned ct = 0; for(int d = 0; d < MDFNGameInfo->InputInfo->Types[x].NumTypes; d++) { if(!strcasecmp(MDFNGameInfo->InputInfo->Types[x].DeviceInfo[d].ShortName, PortDeviceCache[x])) { ct = d; break; } } //printf("%d, 0x%02x\n", x, ct); ld->controller_type[x] = ct; } ld->local_players = local_players; if(nickname != "") memcpy(&sendbuf[4 + sizeof(login_data_t)], nickname.c_str(), nickname.size()); memcpy(&sendbuf[4 + sizeof(login_data_t) + nickname.size()], emu_id, strlen(emu_id)); MDFND_SendData(&sendbuf[0], sendbuf.size()); TotalInputStateSize = 0; for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++) TotalInputStateSize += PortDataLenCache[x]; // Hack so the server can always encode its command data length properly(a matching "hack" exists in the server). if(TotalInputStateSize < 4) TotalInputStateSize = 4; TotalInputStateSize = TotalInputStateSize; LocalPlayersMask = 0; LocalInputStateSize = 0; Joined = false; // // // MDFN_FlushGameCheats(0); /* Save our pre-netplay cheats. */ if(MDFNMOV_IsPlaying()) /* Recording's ok during netplay, playback is not. */ MDFNMOV_Stop(); } catch(std::exception &e) { NetError("%s", e.what()); return(false); } //printf("%d\n", TotalInputStateSize); return(1); }