Пример #1
0
void D_CheckNetGame(void)
{
  packet_header_t *packet = Z_Malloc(sizeof(packet_header_t)+1, PU_STATIC, NULL);

  if (server) {
    lprintf(LO_INFO, "D_CheckNetGame: waiting for server to signal game start\n");
    do {
      while (!I_GetPacket(packet, sizeof(packet_header_t)+1)) {
        packet_set(packet, PKT_GO, 0);
	*(uint8_t*)(packet+1) = consoleplayer;
	I_SendPacket(packet, sizeof(packet_header_t)+1);
	I_uSleep(100000);
      }
    } while (packet->type != PKT_GO);
  }
  Z_Free(packet);
}
Пример #2
0
void D_CheckNetGame(void)
{
  packet_header_t *packet = Z_Malloc(sizeof(packet_header_t)+1, PU_STATIC, NULL);

  if (server) {
    lprintf(LO_INFO, "D_CheckNetGame: waiting for server to signal game start\n");
#ifdef USE_ANDROID
    jni_info_msg("Waiting for server to signal game start!", TT_LONG_DELAY | TT_COLOR_RED);
#endif
    do {
      while (!I_GetPacket(packet, sizeof(packet_header_t)+1)) {
        packet_set(packet, PKT_GO, 0);
	*(byte*)(packet+1) = consoleplayer;
	I_SendPacket(packet, sizeof(packet_header_t)+1);
	I_uSleep(100000);
      }
    } while (packet->type != PKT_GO);
  }
  Z_Free(packet);
}
Пример #3
0
void D_InitNetGame (void)
{
  int i;
  int numplayers = 1;

  i = M_CheckParm("-net");
  if (i && i < myargc-1) i++;

  if (!(netgame = server =  !!i)) {
    playeringame[consoleplayer = 0] = TRUE;
    // e6y
    // for play, recording or playback using "single-player coop" mode.
    // Equivalent to using prboom_server with -N 1
    netgame = M_CheckParm("-solo-net") || M_CheckParm("-net1");
  } else {
    // Get game info from server
    packet_header_t *packet = Z_Malloc(1000, PU_STATIC, NULL);
    struct setup_packet_s *sinfo = (void*)(packet+1);
  struct { packet_header_t head; short pn; } PACKEDATTR initpacket;

    I_InitNetwork();
  udp_socket = I_Socket(0);
  I_ConnectToServer(myargv[i]);

    do
    {
      do { 
	// Send init packet
	initpacket.pn = doom_htons(wanted_player_number);
	packet_set(&initpacket.head, PKT_INIT, 0);
	I_SendPacket(&initpacket.head, sizeof(initpacket));
	I_WaitForPacket(5000);
      } while (!I_GetPacket(packet, 1000));
      if (packet->type == PKT_DOWN) I_Error("Server aborted the game");
    } while (packet->type != PKT_SETUP);

    // Get info from the setup packet
    consoleplayer = sinfo->yourplayer;
    compatibility_level = sinfo->complevel;
    G_Compatibility();
    startskill = sinfo->skill;
    deathmatch = sinfo->deathmatch;
    startmap = sinfo->level;
    startepisode = sinfo->episode;
    ticdup = sinfo->ticdup;
    xtratics = sinfo->extratic;
    G_ReadOptions(sinfo->game_options);

    lprintf(LO_INFO, "\tjoined game as player %d/%d; %d WADs specified\n",
      consoleplayer+1, numplayers = sinfo->players, sinfo->numwads);
    {
      char *p = sinfo->wadnames;
      int i = sinfo->numwads;

      while (i--) {
  D_AddFile(p, source_net);
  p += strlen(p) + 1;
      }
    }
    Z_Free(packet);
  }
  localcmds = netcmds[displayplayer = consoleplayer];
  for (i=0; i<numplayers; i++)
    playeringame[i] = TRUE;
  for (; i<MAXPLAYERS; i++)
    playeringame[i] = FALSE;
  if (!playeringame[consoleplayer]) I_Error("D_InitNetGame: consoleplayer not in game");
}
Пример #4
0
void NetUpdate(void)
{
  static int lastmadetic;
  if (isExtraDDisplay)
    return;
  if (server) { // Receive network packets
    size_t recvlen;
    packet_header_t *packet = Z_Malloc(10000, PU_STATIC, NULL);
    while ((recvlen = I_GetPacket(packet, 10000))) {
      switch(packet->type) {
      case PKT_TICS:
  {
    uint8_t *p = (void*)(packet+1);
    int tics = *p++;
    unsigned long ptic = doom_ntohl(packet->tic);
    if (ptic > (unsigned)remotetic) { // Missed some
      packet_set(packet, PKT_RETRANS, remotetic);
      *(uint8_t*)(packet+1) = consoleplayer;
      I_SendPacket(packet, sizeof(*packet)+1);
    } else {
      if (ptic + tics <= (unsigned)remotetic) break; // Will not improve things
      remotetic = ptic;
      while (tics--) {
        int players = *p++;
        while (players--) {
            int n = *p++;
            RawToTic(&netcmds[n][remotetic%BACKUPTICS], p);
            p += sizeof(ticcmd_t);
        }
        remotetic++;
      }
    }
  }
  break;
      case PKT_RETRANS: // Resend request
          remotesend = doom_ntohl(packet->tic);
          break;
      case PKT_DOWN: // Server downed
  {
    int j;
    for (j=0; j<MAXPLAYERS; j++)
      if (j != consoleplayer) playeringame[j] = FALSE;
    server = FALSE;
    doom_printf("Server is down\nAll other players are no longer in the game\n");
  }
  break;
      case PKT_EXTRA: // Misc stuff
      case PKT_QUIT: // Player quit
  // Queue packet to be processed when its tic time is reached
  queuedpacket = Z_Realloc(queuedpacket, ++numqueuedpackets * sizeof *queuedpacket,
         PU_STATIC, NULL);
  queuedpacket[numqueuedpackets-1] = Z_Malloc(recvlen, PU_STATIC, NULL);
  memcpy(queuedpacket[numqueuedpackets-1], packet, recvlen);
  break;
      case PKT_BACKOFF:
        /* cph 2003-09-18 -
	 * The server sends this when we have got ahead of the other clients. We should
	 * stall the input side on this client, to allow other clients to catch up.
	 */
        lastmadetic++;
	break;
      default: // Other packet, unrecognised or redundant
  break;
      }
    }
    Z_Free(packet);
  }
  { // Build new ticcmds
    int newtics = I_GetTime() - lastmadetic;
    newtics = (newtics > 0 ? newtics : 0);
    lastmadetic += newtics;
    if (ffmap) newtics++;
    while (newtics--) {
      I_StartTic();
      if (maketic - gametic > BACKUPTICS/2) break;
      G_BuildTiccmd(&localcmds[maketic%BACKUPTICS]);
      maketic++;
    }
    if (server && maketic > remotesend) { // Send the tics to the server
      int sendtics;
      remotesend -= xtratics;
      if (remotesend < 0) remotesend = 0;
      sendtics = maketic - remotesend;
      {
  size_t pkt_size = sizeof(packet_header_t) + 2 + sendtics * sizeof(ticcmd_t);
  packet_header_t *packet = Z_Malloc(pkt_size, PU_STATIC, NULL);

  packet_set(packet, PKT_TICC, maketic - sendtics);
  *(uint8_t*)(packet+1) = sendtics;
  *(((uint8_t*)(packet+1))+1) = consoleplayer;
  {
    void *tic = ((uint8_t*)(packet+1)) +2;
    while (sendtics--) {
      TicToRaw(tic, &localcmds[remotesend++%BACKUPTICS]);
      tic = (uint8_t *)tic + sizeof(ticcmd_t);
    }
  }
  I_SendPacket(packet, pkt_size);
  Z_Free(packet);
      }
    }
  }
}
Пример #5
0
boolean D_NetGetWad(const char* name)
{
#if defined(HAVE_WAIT_H)
  size_t psize = sizeof(packet_header_t) + strlen(name) + 500;
  packet_header_t *packet;
  boolean done = FALSE;

  if (!server || strchr(name, '/')) return FALSE; // If it contains path info, reject

  do {
    // Send WAD request to remote
    packet = Z_Malloc(psize, PU_STATIC, NULL);
    packet_set(packet, PKT_WAD, 0);
    *(uint8_t*)(packet+1) = consoleplayer;
    strcpy(1+(uint8_t*)(packet+1), name);
    I_SendPacket(packet, sizeof(packet_header_t) + strlen(name) + 2);

    I_uSleep(10000);
  } while (!I_GetPacket(packet, psize) || (packet->type != PKT_WAD));
  Z_Free(packet);

  if (!strcasecmp((void*)(packet+1), name)) {
    pid_t pid;
    int   rv;
    uint8_t *p = (uint8_t*)(packet+1) + strlen(name) + 1;

    /* Automatic wad file retrieval using wget (supports http and ftp, using URLs)
     * Unix systems have all these commands handy, this kind of thing is easy
     * Any windo$e port will have some awkward work replacing these.
     */
    /* cph - caution here. This is data from an untrusted source.
     * Don't pass it via a shell. */
    if ((pid = fork()) == -1)
      perror("fork");
    else if (!pid) {
      /* Child chains to wget, does the download */
      execlp("wget", "wget", p, NULL);
    }
    /* This is the parent, i.e. main LxDoom process */
    wait(&rv);
    if (!(done = !access(name, R_OK))) {
      if (!strcmp(p+strlen(p)-4, ".zip")) {
  p = strrchr(p, '/')+1;
  if ((pid = fork()) == -1)
    perror("fork");
  else if (!pid) {
    /* Child executes decompressor */
    execlp("unzip", "unzip", p, name, NULL);
  }
  /* Parent waits for the file */
  wait(&rv);
  done = !!access(name, R_OK);
      }
      /* Add more decompression protocols here as desired */
    }
    Z_Free(buffer);
  }
  return done;
#else /* HAVE_WAIT_H */
  return FALSE;
#endif
}
Пример #6
0
void D_InitNetGame (void)
{
	int i;
	int numplayers = 1;

	i = M_CheckParm("-net");
	if (i && i < myargc-1) i++;

	server = netgame;

	if (!netgame)
	{
		playeringame[consoleplayer = 0] = true;
	} else {
		StartWifi();
  
		// Get game info from server
		packet_header_t *packet = Z_Malloc(1000, PU_STATIC, NULL);
		
		struct setup_packet_s *sinfo = (void*)(packet+1);
		
		struct { packet_header_t head; short pn; } PACKEDATTR initpacket;

		iprintf("I_InitNetwork()\n");
		I_InitNetwork();
		udp_socket = I_Socket(0);
		
		//I_ConnectToServer(myargv[i]);
		
		iprintf("I_ConnectToServer()\n");
		
		if (I_ConnectToServer(server_address[0]) != 0) iprintf("FAILURE!\n");
		
		iprintf("Connected?\n");

		do
		{
			iprintf("Send Init Packet\n");
			
			do
			{ 
				// Send init packet
				initpacket.pn = doom_htons(wanted_player_number);
				packet_set(&initpacket.head, PKT_INIT, 0);
				I_SendPacket(&initpacket.head, sizeof(initpacket));
				iprintf("Wait for packet\n");
				I_WaitForPacket(5000);
				iprintf("Done\n");
			} while (!I_GetPacket(packet, 1000));
			
			iprintf("Got it!\n");
			
			if (packet->type == PKT_DOWN) I_Error("Server aborted the game");
			
		} while (packet->type != PKT_SETUP);
		
		iprintf("Out of loop!\n");

		// Once we have been accepted by the server, we should tell it when we leave
		atexit(D_QuitNetGame);

		// Get info from the setup packet
		consoleplayer = sinfo->yourplayer;
		compatibility_level = sinfo->complevel;
		G_Compatibility();
		startskill = sinfo->skill;
		deathmatch = sinfo->deathmatch;
		startmap = sinfo->level;
		startepisode = sinfo->episode;
		ticdup = sinfo->ticdup;
		xtratics = sinfo->extratic;
		
		G_ReadOptions(sinfo->game_options);

		lprintf(LO_INFO, "\tjoined game as player %d/%d; %d WADs specified\n",
		consoleplayer+1, numplayers = sinfo->players, sinfo->numwads);
		
		{
			char *p = sinfo->wadnames;
			int i = sinfo->numwads;

			while (i--)
			{
				D_AddFile(p, source_net);
				p += strlen(p) + 1;
			}
		}
		
		Z_Free(packet);
	}
  
	localcmds = netcmds[displayplayer = consoleplayer];
	
	for (i=0; i<numplayers; i++)
		playeringame[i] = true;
		
	for (; i<MAXPLAYERS; i++)
		playeringame[i] = false;
		
	if (!playeringame[consoleplayer]) I_Error("D_InitNetGame: consoleplayer not in game");
}
Пример #7
0
int main(int argc, char** argv)
{
  int localport = 5030, numplayers = 2, xtratics = 0, ticdup = 1;
  int exectics = 0; // gametics completed
  struct setup_packet_s setupinfo = { 2, 0, 1, 1, 1, 0, 3};
  char**wadname = NULL;
  char**wadget = NULL;
  int numwads = 0;
  {
    int opt;
    byte *gameopt = setupinfo.game_options;

    memcpy(gameopt, &def_game_options, sizeof (setupinfo.game_options));
    while ((opt = getopt(argc, argv, "p:e:l:adrfns:c:N:x:t:vw:")) != EOF)
      switch (opt) {
      case 't':
	if (optarg) ticdup = atoi(optarg);
	break;
      case 'x':
	if (optarg) xtratics = atoi(optarg);
	break;
      case 'p':
	if (optarg) localport = atoi(optarg);
	break;
      case 'e':
	if (optarg) setupinfo.episode = atoi(optarg);
	break;
      case 'l':
	if (optarg) setupinfo.level = atoi(optarg);
	break;
      case 'a':
	setupinfo.deathmatch = 2;
	break;
      case 'd':
	setupinfo.deathmatch = 1;
	break;
      case 'r':
	setupinfo.game_options[6] = 1;
	break;
      case 'f':
	setupinfo.game_options[7] = 1;
	break;
      case 'n':
	setupinfo.game_options[8] = 1;
	break;
      case 's':
	if (optarg) setupinfo.skill = atoi(optarg);
	break;
      case 'N':
	if (optarg) setupinfo.players = numplayers = atoi(optarg);
	break;
      case 'v':
	verbose++;
	break;
      case 'w':
	if (optarg) {
	  char *p;
	  wadname = realloc(wadname, ++numwads * sizeof *wadname);
	  wadget  = realloc(wadget ,   numwads * sizeof *wadget );
	  wadname[numwads-1] = strdup(optarg);
	  if ((p = strchr(wadname[numwads-1], ','))) {
	    *p++ = 0; wadget[numwads-1] = p;
	  } else wadget[numwads-1] = NULL;
	}
	break;
      }
  }

  setupinfo.ticdup = ticdup; setupinfo.extratic = xtratics;
  *(int*)(&setupinfo.game_options[10]) = time(NULL); // random number seed
  I_InitSockets(localport);

  printf("Listening on port %d, waiting for %d players\n", localport, numplayers);

  { // no players initially
    int i;
    for (i=0; i<MAXPLAYERS; i++)
      playerjoingame[i] = INT_MAX; playerleftgame[i] = 0;

    // Print wads
    for (i=0; i<numwads; i++)
      printf("Wad %s (%s)\n", wadname[i], wadget[i]);
  }

  // Exit and signal handling
  atexit(doexit); // heh
  signal(SIGTERM, sig_handler);
  signal(SIGINT , sig_handler);
  signal(SIGQUIT, sig_handler);
  signal(SIGKILL, sig_handler);
  signal(SIGHUP , sig_handler);
  
  {
    int remoteticfrom[MAXPLAYERS] = { 0, 0, 0, 0 };
    int remoteticto[MAXPLAYERS] = { 0, 0, 0, 0 };
    int curplayers = 0;
    boolean ingame = false;
    ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];

    while (1) {
      {
	packet_header_t *packet = malloc(10000);
	size_t len;
	
	usleep(10000);
	while ((len = I_GetPacket(packet, 10000))) {
	  if (verbose>2) printf("Received packet:");
	  switch (packet->type) {
	  case PKT_INIT:
	    printf("INIT\n");
	    if (!ingame) {
	      {
		int n;
		struct setup_packet_s *sinfo = (void*)(packet+1);
		const char *rname = (void*)((short*)(packet+1)+1);
		
		// Add player to the game
		for (n=0; n<MAXPLAYERS; n++)
		  if (playerjoingame[n] == INT_MAX) break;

		if (n == MAXPLAYERS) break; // Full game
		playerjoingame[n] = 0;
		remoteaddr[n] = sentfrom;
		remoteaddr[n].sin_port = *(short*)(packet+1);

		if (!memchr(rname,0,1000)) rname = "Invalid";
		printf("%s(%s:%u) joined\n", rname,
		       inet_ntoa(remoteaddr[n].sin_addr), 
		       ntohs(remoteaddr[n].sin_port));
		{
		  int i;
		  size_t extrabytes = 0;
		  // Send setup packet
		  packet->type = PKT_SETUP;
		  packet->tic = 0;
		  memcpy(sinfo, &setupinfo, sizeof setupinfo);
		  sinfo->yourplayer = n;
		  sinfo->numwads = numwads;
		  for (i=0; i<numwads; i++) {
		    strcpy(sinfo->wadnames + extrabytes, wadname[i]);
		    extrabytes += strlen(wadname[i]) + 1;
		  }
		  I_SendPacketTo(packet, sizeof *packet + sizeof setupinfo + extrabytes, 
				 remoteaddr+n);
		  usleep(10000);
		  I_SendPacketTo(packet, sizeof *packet + sizeof setupinfo + extrabytes, 
				 remoteaddr+n);
		}
	      }
	    }
	    break;
	  case PKT_GO:
	    if (!ingame) {
	      int from = *(byte*)(packet+1);

	      if (playerleftgame[from] == INT_MAX) break;
	      playerleftgame[from] = INT_MAX;
	      if (++curplayers == numplayers) {
		ingame=true;
		printf("All players joined, beginning game.\n");
		packet->type = PKT_GO; packet->tic = 0;
		BroadcastPacket(packet, sizeof *packet);
		usleep(10000);
		BroadcastPacket(packet, sizeof *packet);
		usleep(100000);
	      }
	    }
	    break;
	  case PKT_TICC:
	    {
	      byte tics = *(byte*)(packet+1);
	      int from = *(((byte*)(packet+1))+1);

	      if (verbose>2)
		printf("tics %d - %d from %d\n", packet->tic, packet->tic + tics - 1, from);
	      if (packet->tic > remoteticfrom[from]) {
		// Missed tics, so request a resend
		packet->tic = remoteticfrom[from];
		packet->type = PKT_RETRANS;
		I_SendPacketTo(packet, sizeof *packet, remoteaddr+from);
	      } else {
		ticcmd_t *newtic = (void*)(((byte*)(packet+1))+2);
		if (packet->tic + tics < remoteticfrom[from]) break; // Won't help
		remoteticfrom[from] = packet->tic;
		while (tics--)
		  netcmds[from][remoteticfrom[from]++%BACKUPTICS] =  *newtic++;
	      }
	    }
	    break;
	  case PKT_RETRANS:
	    {
	      int from = *(byte*)(packet+1);
	      if (verbose>2) printf("%d requests resend from %d\n", from, packet->tic);
	      remoteticto[from] = packet->tic;
	    }
	    break;
	  case PKT_QUIT:
	    { 
	      int from = *(byte*)(packet+1);

	      if (verbose>2) printf("%d quits at %d\n", from, packet->tic);
	      if (playerleftgame[from] == INT_MAX) { // In the game
		playerleftgame[from] = packet->tic;
		if (ingame && !--curplayers) exit(0); // All players have exited
	      }
	    }
	    // Fall through and broadcast it
	  case PKT_EXTRA:
	    BroadcastPacket(packet, len);
	    if (packet->type == PKT_EXTRA) {
	      if (verbose>2) printf("misc from %d\n", *(((byte*)(packet+1))+1));
	    }
	    break;
	  case PKT_WAD:
	    {
	      int i;
	      int from = *(byte*)(packet+1);
	      char *name = 1 + (char*)(packet+1);
	      size_t size = sizeof(packet_header_t);
	      packet_header_t *reply;

	      if (verbose) printf("Request for %s ", name);
	      for (i=0; i<numwads; i++)
		if (!strcasecmp(name, wadname[i]))
		  break;

	      if ((i==numwads) || !wadget[i]) {
		if (verbose) printf("n/a\n");
		*(char*)(packet+1) = 0;
		I_SendPacketTo(packet, size+1, remoteaddr + from); 
	      } else {
		size += strlen(wadname[i]) + strlen(wadget[i]) + 2;
		reply = malloc(size);
		reply->type = PKT_WAD; reply->tic = 0;
		strcpy((char*)(reply+1), wadname[i]);
		strcpy((char*)(reply+1) + strlen(wadname[i]) + 1, wadget[i]);
		printf("sending %s\n", wadget[i]);
		I_SendPacketTo(reply, size, remoteaddr + from);
		free(reply);
	      }
	    }
	    break;
	  default:
	    printf("Unrecognised packet type %d\n", packet->type);
	    break;
	  }
	}
	free(packet);
      }

      if (ingame) { // Run some tics
	int lowtic = INT_MAX;
	int i;
	for (i=0; i<MAXPLAYERS; i++) 
	  if (playeringame(i))
	    if (remoteticfrom[i]<lowtic)
	      lowtic = remoteticfrom[i];

	if (verbose>1) printf("%d new tics can be run\n", lowtic - exectics);

	if (lowtic > exectics) 
	  exectics = lowtic; // count exec'ed tics
	// Now send all tics up to lowtic
	for (i=0; i<MAXPLAYERS; i++) 
	  if (playeringame(i)) {
	    int tics;
	    if (lowtic <= remoteticto[i]) continue;
	    remoteticto[i] -= xtratics;
	    tics = lowtic - remoteticto[i]; 
	    {
	      packet_header_t *packet = malloc(sizeof(packet_header_t) + 1 +
				 tics * (1 + numplayers * (1 + sizeof(ticcmd_t))));
	      byte *p = (void*)(packet+1);
	      packet->type = PKT_TICS; packet->tic = remoteticto[i] - xtratics;
	      *p++ = tics;
	      if (verbose>1) printf("sending %d tics to %d\n", tics, i);
	      while (tics--) {
		int j, playersthistic = 0;
		byte *q = p++;
		for (j=0; j<MAXPLAYERS; j++)
		  if ((playerjoingame[j] < remoteticto[i]) && 
		      (playerleftgame[j] > remoteticto[i])) {
		    *p++ = j;
		    memcpy(p, &netcmds[j][remoteticto[i]%BACKUPTICS], sizeof(ticcmd_t));
		    p += sizeof(ticcmd_t);
		    playersthistic++;
		  }
		*q = playersthistic;
		remoteticto[i]++;
	      }
	      I_SendPacketTo(packet, p - ((byte*)packet), remoteaddr+i);
	      free(packet);
	    }
	  }
      }
      { // Statistics reporting
	static int counter = 0;
	static int lastrecvdbytes, lastsentbytes;
	int fh;

	if (exectics && !(counter++%100)) {
	  char buf[1000];
	  sprintf(buf, "lxdoom-game-server-stats.%u", getpid());
	  fh = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
	  sprintf(buf, "Players %d, tic %d\n\tSent\tReceived\n"
		  "Now\t%d\t%d\nPer tic\t%d\t%d\n", 
		  curplayers, exectics, 
		  sentbytes - lastsentbytes, recvdbytes - lastrecvdbytes, 
		  sentbytes/exectics, recvdbytes/exectics);
	  write(fh, buf, strlen(buf));
	  close(fh);
	  lastrecvdbytes = recvdbytes; lastsentbytes = sentbytes;
	}
      }
    }
  }
}