add IPv4 multicasting support
This commit is contained in:
parent
fa1207dfe1
commit
922c3542fe
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2003-10-12 Aaron Plattner <plattner@caltech.edu>
|
||||
|
||||
* arch/linux/Makefile.am, arch/linux/ipx_bsd.c,
|
||||
arch/linux/ipx_kali.c, arch/linux/ipx_mcast4.c,
|
||||
arch/linux/ipx_udp.c, arch/linux/linuxnet.c,
|
||||
arch/linux/include/ipx_drv.h, arch/linux/include/ipx_mcast4.h,
|
||||
arch/win32/Makefile.am, arch/win32/ipx_drv.h,
|
||||
arch/win32/ipx_mcast4.c, arch/win32/ipx_udp.c,
|
||||
arch/win32/ipx_win.c, arch/win32/winnet.c,
|
||||
arch/win32/include/ipx_mcast4.h, include/ipx.h, main/menu.c,
|
||||
main/multi.h: add IPv4 multicasting support
|
||||
|
||||
2003-10-11 Bradley Bell <btb@icculus.org>
|
||||
|
||||
* main/endlevel.c, main/piggy.c: fixed endlevel stuff
|
||||
|
|
|
@ -5,7 +5,7 @@ noinst_LIBRARIES = libarch_linux.a
|
|||
INCLUDES = -I$(top_srcdir)/arch/include -I$(top_srcdir)/include -I$(top_srcdir)/main -I$(srcdir)/include
|
||||
|
||||
if USE_NETWORK
|
||||
NETWORK_SRCS = ipx_kali.c ipx_udp.c linuxnet.c ukali.c
|
||||
NETWORK_SRCS = ipx_kali.c ipx_udp.c linuxnet.c ukali.c ipx_mcast4.c
|
||||
if USE_NATIVE_IPX
|
||||
IPX_SRCS = ipx_bsd.c
|
||||
endif
|
||||
|
@ -18,7 +18,7 @@ endif
|
|||
libarch_linux_a_SOURCES = ${NETWORK_SRCS} ${IPX_SRCS} ${JOYSTICK_SRCS} findfile.c init.c
|
||||
|
||||
EXTRA_libarch_linux_a_SOURCES = \
|
||||
ipx_bsd.c ipx_kali.c ipx_udp.c linuxnet.c ukali.c \
|
||||
ipx_bsd.c ipx_kali.c ipx_mcast4.c ipx_udp.c linuxnet.c ukali.c \
|
||||
joydefs.c joystick.c
|
||||
|
||||
EXTRA_DIST = ${EXTRA_SUBDIRS} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx_drv.h,v 1.4 2003-03-13 00:20:21 btb Exp $ */
|
||||
/* $Id: ipx_drv.h,v 1.5 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* IPX driver interface
|
||||
|
@ -63,6 +63,10 @@ struct ipx_driver {
|
|||
int (*ReceivePacket)(ipx_socket_t *s, char *buffer, int bufsize,
|
||||
struct ipx_recv_data *rec);
|
||||
int (*PacketReady)(ipx_socket_t *s);
|
||||
void (*InitNetgameAuxData)(ipx_socket_t *s, u_char buf[]);
|
||||
int (*HandleNetgameAuxData)(ipx_socket_t *s, const u_char buf[]);
|
||||
void (*HandleLeaveGame)(ipx_socket_t *s);
|
||||
int (*SendGamePacket)(ipx_socket_t *s, u_char *data, int dataLen);
|
||||
};
|
||||
|
||||
int ipx_general_PacketReady(ipx_socket_t *s);
|
||||
|
|
15
arch/linux/include/ipx_mcast4.h
Normal file
15
arch/linux/include/ipx_mcast4.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* $Id: ipx_mcast4.h,v 1.1 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* FIXME: add description
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _IPX_MCAST4_H
|
||||
#define _IPX_MCAST4_H
|
||||
#include "ipx_drv.h"
|
||||
|
||||
extern struct ipx_driver ipx_mcast4;
|
||||
#define IPX_MCAST4_VERSION 0
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx_bsd.c,v 1.6 2003-03-13 00:20:21 btb Exp $ */
|
||||
/* $Id: ipx_bsd.c,v 1.7 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* IPX driver using BSD style sockets
|
||||
|
@ -229,5 +229,9 @@ struct ipx_driver ipx_bsd = {
|
|||
ipx_bsd_CloseSocket,
|
||||
ipx_bsd_SendPacket,
|
||||
ipx_bsd_ReceivePacket,
|
||||
ipx_general_PacketReady
|
||||
ipx_general_PacketReady,
|
||||
NULL, // InitNetgameAuxData
|
||||
NULL, // HandleNetgameAuxData
|
||||
NULL, // HandleLeaveGame
|
||||
NULL // SendGamePacket
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx_kali.c,v 1.5 2003-03-13 00:20:21 btb Exp $ */
|
||||
/* $Id: ipx_kali.c,v 1.6 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* IPX driver for KaliNix interface
|
||||
|
@ -123,5 +123,9 @@ struct ipx_driver ipx_kali = {
|
|||
ipx_kali_CloseSocket,
|
||||
ipx_kali_SendPacket,
|
||||
ipx_kali_ReceivePacket,
|
||||
ipx_general_PacketReady
|
||||
ipx_general_PacketReady,
|
||||
NULL, // InitNetgameAuxData
|
||||
NULL, // HandleNetgameAuxData
|
||||
NULL, // HandleLeaveGame
|
||||
NULL // SendGamePacket
|
||||
};
|
||||
|
|
331
arch/linux/ipx_mcast4.c
Normal file
331
arch/linux/ipx_mcast4.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/* $Id: ipx_mcast4.c,v 1.1 2003-10-12 09:17:47 btb Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* "ipx driver" for IPv4 multicasting
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <conf.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "pstypes.h"
|
||||
#include "ipx_mcast4.h"
|
||||
#include "args.h"
|
||||
#include "error.h"
|
||||
#include "newmenu.h"
|
||||
#include "../../main/multi.h"
|
||||
|
||||
//#define IPX_MCAST4_DEBUG
|
||||
|
||||
extern unsigned char ipx_MyAddress[10];
|
||||
|
||||
#define UDP_BASEPORT 28342
|
||||
#define PORTSHIFT_TOLERANCE 0x100
|
||||
#define MAX_PACKETSIZE 8192
|
||||
|
||||
/* OUR port. Can be changed by "@X[+=]..." argument (X is the shift value)
|
||||
*/
|
||||
static int baseport=UDP_BASEPORT;
|
||||
|
||||
static struct in_addr game_addr; // The game's multicast address
|
||||
|
||||
#define MSGHDR "IPX_mcast4: "
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
static void msg(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fputs(MSGHDR, stdout);
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
putchar('\n');
|
||||
}
|
||||
#else
|
||||
#define msg(m...)
|
||||
#endif
|
||||
|
||||
#define FAIL(m...) do{ nm_messagebox("Error", 1, "Ok", ##m); return -1; } while (0)
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
/* Dump raw form of IP address/port by fancy output to user
|
||||
*/
|
||||
static void dumpraddr(unsigned char *a)
|
||||
{
|
||||
short port;
|
||||
|
||||
printf("[%u.%u.%u.%u]", a[0], a[1], a[2], a[3]);
|
||||
port=(signed short)ntohs(*(unsigned short *)(a+4));
|
||||
if (port) printf(":%+d",port);
|
||||
}
|
||||
|
||||
/* Like dumpraddr() but for structure "sockaddr_in"
|
||||
*/
|
||||
static void dumpaddr(struct sockaddr_in *sin)
|
||||
{
|
||||
unsigned short ports;
|
||||
unsigned char qhbuf[8];
|
||||
|
||||
memcpy(qhbuf + 0, &sin->sin_addr, 4);
|
||||
ports = htons(((short)ntohs(sin->sin_port)) - UDP_BASEPORT);
|
||||
memcpy(qhbuf + 4, &ports, 2);
|
||||
dumpraddr(qhbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The multicast address for Descent 2 game announcements.
|
||||
// TODO: Pick a better address for this
|
||||
#define DESCENT2_ANNOUNCE_ADDR inet_addr("239.255.1.2")
|
||||
|
||||
/* Open the socket and subscribe to the multicast session */
|
||||
static int ipx_mcast4_OpenSocket(ipx_socket_t *sk, int port)
|
||||
{
|
||||
u_char loop;
|
||||
struct ip_mreq mreq;
|
||||
struct sockaddr_in sin;
|
||||
int ttl = 128;
|
||||
|
||||
if((sk->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
{
|
||||
sk->fd = -1;
|
||||
FAIL("socket() creation failed on port %d: %m", port);
|
||||
}
|
||||
|
||||
// Bind to the port
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
sin.sin_port = htons(baseport);
|
||||
if (bind(sk->fd, (struct sockaddr *)&sin, sizeof(sin)))
|
||||
{
|
||||
if (close(sk->fd))
|
||||
msg("close() failed during error recovery: %m");
|
||||
sk->fd = -1;
|
||||
FAIL("bind() to UDP port %d failed: %m", baseport);
|
||||
}
|
||||
|
||||
// Set the TTL so the packets can get out of the local network.
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||
FAIL("setsockopt() failed to set TTL to 128");
|
||||
|
||||
// Disable multicast loopback
|
||||
loop = 0;
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)
|
||||
FAIL("setsockopt() failed to disable multicast loopback: %m");
|
||||
|
||||
// Subscribe to the game announcement address
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_multiaddr.s_addr = DESCENT2_ANNOUNCE_ADDR;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
FAIL("setsockopt() failed to subscribe to the game announcement multicast group");
|
||||
|
||||
// We're not subscribed to a game address yet
|
||||
game_addr.s_addr = 0;
|
||||
|
||||
sk->socket = port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipx_mcast4_CloseSocket(ipx_socket_t *sk)
|
||||
{
|
||||
if(close(sk->fd) < 0)
|
||||
msg("Close failed");
|
||||
sk->fd = -1;
|
||||
}
|
||||
|
||||
static int ipx_mcast4_SendPacket(ipx_socket_t *sk, IPXPacket_t *IPXHeader, u_char *data, int dataLen)
|
||||
{
|
||||
struct sockaddr_in toaddr;
|
||||
int i;
|
||||
|
||||
msg("SendPacket enter, dataLen=%d", dataLen);
|
||||
|
||||
if(dataLen < 0 || dataLen > MAX_PACKETSIZE)
|
||||
return -1;
|
||||
|
||||
toaddr.sin_family = AF_INET;
|
||||
memcpy(&toaddr.sin_addr, IPXHeader->Destination.Node + 0, 4);
|
||||
//toaddr.sin_port = htons(((short)ntohs(*(unsigned short *)(IPXHeader->Destination.Node + 4))) + UDP_BASEPORT);
|
||||
// For now, just use the same port for everything
|
||||
toaddr.sin_port = htons(UDP_BASEPORT);
|
||||
|
||||
// If it's the broadcast address, then we want to send it to the
|
||||
// GAME ANNOUNCEMENT address.
|
||||
// Data to be sent to the GAME has the destination already set by
|
||||
// ipx_mcast4_SendGamePacket
|
||||
if(toaddr.sin_addr.s_addr == INADDR_BROADCAST)
|
||||
toaddr.sin_addr.s_addr = DESCENT2_ANNOUNCE_ADDR;
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
printf(MSGHDR "sendto((%d),Node=[4] %02X %02X,Socket=%02X %02X,s_port=%u,",
|
||||
dataLen,
|
||||
IPXHeader->Destination.Node[4], IPXHeader->Destination.Node[5],
|
||||
IPXHeader->Destination.Socket[0], IPXHeader->Destination.Socket[1],
|
||||
ntohs(toaddr.sin_port));
|
||||
dumpaddr(&toaddr);
|
||||
puts(").");
|
||||
#endif
|
||||
|
||||
i = sendto(sk->fd, data, dataLen, 0, (struct sockaddr *)&toaddr, sizeof(toaddr));
|
||||
return i;
|
||||
}
|
||||
|
||||
static int ipx_mcast4_ReceivePacket(ipx_socket_t *sk, char *outbuf, int outbufsize, struct ipx_recv_data *rd)
|
||||
{
|
||||
int size;
|
||||
struct sockaddr_in fromaddr;
|
||||
int fromaddrsize = sizeof(fromaddr);
|
||||
|
||||
if((size = recvfrom(sk->fd, outbuf, outbufsize, 0, (struct sockaddr*)&fromaddr, &fromaddrsize)) < 0)
|
||||
return -1;
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
printf(MSGHDR "Got packet from ");
|
||||
dumpaddr(&fromaddr);
|
||||
puts("");
|
||||
#endif
|
||||
|
||||
// We have the packet, now fill out the receive data.
|
||||
memset(rd, 0, sizeof(*rd));
|
||||
memcpy(rd->src_node, &fromaddr.sin_addr, 4);
|
||||
// TODO: Include the port like in ipx_udp.c
|
||||
rd->pkt_type = 0;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Handle the netgame aux data
|
||||
* Byte 0 is the protocol version number.
|
||||
* Bytes 1-4 are the IPv4 multicast session to join, in network byte order.
|
||||
*/
|
||||
static int ipx_mcast4_HandleNetgameAuxData(ipx_socket_t *sk, const u_char buf[NETGAME_AUX_SIZE])
|
||||
{
|
||||
// Extract the multicast session and subscribe to it. We should
|
||||
// now be getting packets intended for the players of this game.
|
||||
|
||||
// Note that we stay subscribed to the game announcement session,
|
||||
// so we can reply to game info requests
|
||||
struct ip_mreq mreq;
|
||||
int ttl = 128;
|
||||
|
||||
// Check the protocol version
|
||||
if(buf[0] != IPX_MCAST4_VERSION)
|
||||
{
|
||||
FAIL("mcast4 protocol\nversion mismatch!\nGame version is %02x,\nour version is %02x", buf[0], IPX_MCAST4_VERSION);
|
||||
}
|
||||
|
||||
// Get the multicast session
|
||||
memcpy(&game_addr, buf + 1, sizeof(game_addr));
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
{
|
||||
struct sockaddr_in tmpaddr;
|
||||
tmpaddr.sin_addr = game_addr;
|
||||
tmpaddr.sin_port = 0;
|
||||
|
||||
printf("Handling netgame aux data: Subscribing to ");
|
||||
dumpaddr(&tmpaddr);
|
||||
puts("");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set the TTL so the packets can get out of the local network.
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||
FAIL("setsockopt() failed to set TTL to 128");
|
||||
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_multiaddr = game_addr;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
FAIL("setsockopt() failed to subscribe to the game group");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the netgame aux data.
|
||||
* Byte 0 is the protcol version number.
|
||||
* Bytes 1-4 hold the IPv4 multicast session for the game.
|
||||
*/
|
||||
static void ipx_mcast4_InitNetgameAuxData(ipx_socket_t *sk, u_char buf[NETGAME_AUX_SIZE])
|
||||
{
|
||||
Assert(game_addr.s_addr == 0);
|
||||
|
||||
// The first byte is the version number
|
||||
buf[0] = IPX_MCAST4_VERSION;
|
||||
|
||||
// Generate a random session
|
||||
game_addr = inet_makeaddr(239*256 + 255, d_rand() % 0xFFFF);
|
||||
memcpy(buf + 1, &game_addr, sizeof(game_addr));
|
||||
|
||||
// Since we're obviously the hosting machine, subscribe to this address
|
||||
ipx_mcast4_HandleNetgameAuxData(sk, buf);
|
||||
}
|
||||
|
||||
static void ipx_mcast4_HandleLeaveGame(ipx_socket_t *sk)
|
||||
{
|
||||
// We left the game, so unsubscribe from its multicast session
|
||||
struct ip_mreq mreq;
|
||||
|
||||
Assert(game_addr.s_addr != 0);
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
printf("Unsubscribing from game's multicast group: ");
|
||||
dumpraddr(&game_addr.s_addr);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
mreq.imr_multiaddr = game_addr;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
msg("setsockopt() failed unsubscribing from previous group!");
|
||||
game_addr.s_addr = 0;
|
||||
}
|
||||
|
||||
// Send a packet to every member of the game. We can just multicast it here.
|
||||
static int ipx_mcast4_SendGamePacket(ipx_socket_t *sk, ubyte *data, int dataLen)
|
||||
{
|
||||
struct sockaddr_in toaddr;
|
||||
int i;
|
||||
|
||||
memset(&toaddr, 0, sizeof(toaddr));
|
||||
toaddr.sin_addr = game_addr;
|
||||
toaddr.sin_port = htons(UDP_BASEPORT);
|
||||
|
||||
msg("ipx_mcast4_SendGamePacket");
|
||||
|
||||
i = sendto(sk->fd, data, dataLen, 0, (struct sockaddr *)&toaddr, sizeof(toaddr));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// Pull this in from ipx_udp.c since it's the same for us.
|
||||
extern int ipx_udp_GetMyAddress();
|
||||
|
||||
struct ipx_driver ipx_mcast4 = {
|
||||
ipx_udp_GetMyAddress,
|
||||
ipx_mcast4_OpenSocket,
|
||||
ipx_mcast4_CloseSocket,
|
||||
ipx_mcast4_SendPacket,
|
||||
ipx_mcast4_ReceivePacket,
|
||||
ipx_general_PacketReady,
|
||||
ipx_mcast4_InitNetgameAuxData,
|
||||
ipx_mcast4_HandleNetgameAuxData,
|
||||
ipx_mcast4_HandleLeaveGame,
|
||||
ipx_mcast4_SendGamePacket
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx_udp.c,v 1.7 2003-10-03 07:58:14 btb Exp $ */
|
||||
/* $Id: ipx_udp.c,v 1.8 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* IPX driver for native Linux TCP/IP networking (UDP implementation)
|
||||
|
@ -353,7 +353,7 @@ unsigned short ports;
|
|||
/* Startup... Uninteresting parsing...
|
||||
*/
|
||||
|
||||
static int ipx_udp_GetMyAddress(void) {
|
||||
int ipx_udp_GetMyAddress(void) {
|
||||
|
||||
char buf[256];
|
||||
int i;
|
||||
|
@ -610,5 +610,9 @@ struct ipx_driver ipx_udp = {
|
|||
ipx_udp_CloseSocket,
|
||||
ipx_udp_SendPacket,
|
||||
ipx_udp_ReceivePacket,
|
||||
ipx_general_PacketReady
|
||||
ipx_general_PacketReady,
|
||||
NULL, // InitNetgameAuxData
|
||||
NULL, // HandleNetgameAuxData
|
||||
NULL, // HandleLeaveGame
|
||||
NULL // SendGamePacket
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: linuxnet.c,v 1.11 2003-10-10 09:36:34 btb Exp $ */
|
||||
/* $Id: linuxnet.c,v 1.12 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||||
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||||
|
@ -19,6 +19,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <conf.h>
|
||||
#endif
|
||||
|
@ -38,10 +39,14 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#include "ipx.h"
|
||||
#include "ipx_drv.h"
|
||||
#ifdef NATIVE_IPX
|
||||
# include "ipx_bsd.h"
|
||||
# include "ipx_bsd.h"
|
||||
#endif //NATIVE_IPX
|
||||
#include "ipx_kali.h"
|
||||
#include "ipx_udp.h"
|
||||
#include "ipx_mcast4.h"
|
||||
#include "error.h"
|
||||
#include "../../main/player.h" /* for Players */
|
||||
#include "../../main/multi.h" /* for NetPlayers */
|
||||
//added 05/17/99 Matt Mueller - needed to redefine FD_* so that no asm is used
|
||||
//#include "checker.h"
|
||||
//end addition -MM
|
||||
|
@ -105,6 +110,7 @@ void arch_ipx_set_driver(int ipx_driver)
|
|||
#endif //NATIVE_IPX
|
||||
case IPX_DRIVER_KALI: driver = &ipx_kali; break;
|
||||
case IPX_DRIVER_UDP: driver = &ipx_udp; break;
|
||||
case IPX_DRIVER_MCAST4: driver = &ipx_mcast4; break;
|
||||
default: Int3();
|
||||
}
|
||||
}
|
||||
|
@ -174,6 +180,8 @@ void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *ad
|
|||
{
|
||||
u_char buf[MAX_IPX_DATA];
|
||||
IPXPacket_t ipx_header;
|
||||
|
||||
Assert(datasize <= MAX_IPX_DATA+4);
|
||||
|
||||
memcpy(ipx_header.Destination.Network, network, 4);
|
||||
memcpy(ipx_header.Destination.Node, immediate_address, 6);
|
||||
|
@ -373,3 +381,51 @@ void ipx_read_network_file(char * filename)
|
|||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// Initalizes the protocol-specific member of the netgame packet.
|
||||
void ipx_init_netgame_aux_data(ubyte buf[])
|
||||
{
|
||||
if(driver->InitNetgameAuxData)
|
||||
driver->InitNetgameAuxData(&ipx_socket_data, buf);
|
||||
}
|
||||
|
||||
// Handles the protocol-specific member of the netgame packet.
|
||||
int ipx_handle_netgame_aux_data(const ubyte buf[])
|
||||
{
|
||||
if(driver->HandleNetgameAuxData)
|
||||
return driver->HandleNetgameAuxData(&ipx_socket_data, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Notifies the protocol that we're done with a particular game
|
||||
void ipx_handle_leave_game()
|
||||
{
|
||||
if(driver->HandleLeaveGame)
|
||||
driver->HandleLeaveGame(&ipx_socket_data);
|
||||
}
|
||||
|
||||
// Send a packet to every member of the game.
|
||||
int ipx_send_game_packet(ubyte *data, int datasize)
|
||||
{
|
||||
if(driver->SendGamePacket) {
|
||||
u_char buf[MAX_IPX_DATA];
|
||||
|
||||
*(uint *)buf = ipx_packetnum++;
|
||||
memcpy(buf + 4, data, datasize);
|
||||
*(uint *)data = ipx_packetnum++;
|
||||
return driver->SendGamePacket(&ipx_socket_data, buf, datasize + 4);
|
||||
} else {
|
||||
// Loop through all the players unicasting the packet.
|
||||
int i;
|
||||
|
||||
//printf("Sending game packet: N_players = %i\n", N_players);
|
||||
|
||||
for(i=0; i<N_players; i++) {
|
||||
if(Players[i].connected && (i != Player_num))
|
||||
ipx_send_packet_data(data, datasize, NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node,Players[i].net_address);
|
||||
}
|
||||
return datasize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ noinst_LIBRARIES = libarch_win32.a
|
|||
INCLUDES = -I$(top_srcdir)/arch/include -I$(top_srcdir)/include -I$(top_srcdir)/main -I$(srcdir)/include
|
||||
|
||||
if USE_NETWORK
|
||||
NETWORK_SRCS = winnet.c ipx_win.c ipx_udp.c
|
||||
NETWORK_SRCS = ipx_mcast4.c ipx_win.c ipx_udp.c winnet.c
|
||||
endif
|
||||
|
||||
libarch_win32_a_SOURCES = ${NETWORK_SRCS} findfile.c mingw_init.c
|
||||
|
||||
EXTRA_libarch_win32_a_SOURCES = winnet.c ipx_win.c ipx_udp.c
|
||||
EXTRA_libarch_win32_a_SOURCES = ipx_mcast4.c ipx_win.c ipx_udp.c winnet.c
|
||||
|
||||
EXTRA_DIST = ${EXTRA_SUBDIRS} \
|
||||
d1x.ico d1x.rc d3d.ico debug.cpp descent.ico digi.c findfile.c glinit.c gr.c \
|
||||
|
|
15
arch/win32/include/ipx_mcast4.h
Normal file
15
arch/win32/include/ipx_mcast4.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* $Id: ipx_mcast4.h,v 1.1 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* FIXME: add description
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _IPX_MCAST4_H
|
||||
#define _IPX_MCAST4_H
|
||||
#include "ipx_drv.h"
|
||||
|
||||
extern struct ipx_driver ipx_mcast4;
|
||||
#define IPX_MCAST4_VERSION 0
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx_drv.h,v 1.6 2003-10-04 03:18:02 btb Exp $ */
|
||||
/* $Id: ipx_drv.h,v 1.7 2003-10-12 09:17:47 btb Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -67,6 +67,10 @@ struct ipx_driver {
|
|||
int (*ReceivePacket)(ipx_socket_t *s, char *buffer, int bufsize,
|
||||
struct ipx_recv_data *rec);
|
||||
int (*PacketReady)(ipx_socket_t *s);
|
||||
void (*InitNetgameAuxData)(ipx_socket_t *s, u_char buf[]);
|
||||
int (*HandleNetgameAuxData)(ipx_socket_t *s, const u_char buf[]);
|
||||
void (*HandleLeaveGame)(ipx_socket_t *s);
|
||||
int (*SendGamePacket)(ipx_socket_t *s, u_char *data, int dataLen);
|
||||
};
|
||||
|
||||
int ipx_general_PacketReady(ipx_socket_t *s);
|
||||
|
|
332
arch/win32/ipx_mcast4.c
Normal file
332
arch/win32/ipx_mcast4.c
Normal file
|
@ -0,0 +1,332 @@
|
|||
/* $Id: ipx_mcast4.c,v 1.1 2003-10-12 09:17:47 btb Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* "ipx driver" for IPv4 multicasting
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <conf.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include "ipx_mcast4.h"
|
||||
#include "args.h"
|
||||
#include "error.h"
|
||||
#include "../../main/multi.h"
|
||||
|
||||
//#define IPX_MCAST4_DEBUG
|
||||
|
||||
extern unsigned char ipx_MyAddress[10];
|
||||
|
||||
#define UDP_BASEPORT 28342
|
||||
#define PORTSHIFT_TOLERANCE 0x100
|
||||
#define MAX_PACKETSIZE 8192
|
||||
|
||||
/* OUR port. Can be changed by "@X[+=]..." argument (X is the shift value)
|
||||
*/
|
||||
static int baseport=UDP_BASEPORT;
|
||||
|
||||
static struct in_addr game_addr; // The game's multicast address
|
||||
|
||||
#define MSGHDR "IPX_mcast4: "
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
static void msg(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fputs(MSGHDR, stdout);
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
putchar('\n');
|
||||
}
|
||||
#else
|
||||
#define msg(m...)
|
||||
#endif
|
||||
|
||||
#define FAIL(m...) do{ nm_messagebox("Error", 1, "Ok", ##m); return -1; } while (0)
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
/* Dump raw form of IP address/port by fancy output to user
|
||||
*/
|
||||
static void dumpraddr(unsigned char *a)
|
||||
{
|
||||
short port;
|
||||
|
||||
printf("[%u.%u.%u.%u]", a[0], a[1], a[2], a[3]);
|
||||
port=(signed short)ntohs(*(unsigned short *)(a+4));
|
||||
if (port) printf(":%+d",port);
|
||||
}
|
||||
|
||||
/* Like dumpraddr() but for structure "sockaddr_in"
|
||||
*/
|
||||
static void dumpaddr(struct sockaddr_in *sin)
|
||||
{
|
||||
unsigned short ports;
|
||||
unsigned char qhbuf[8];
|
||||
|
||||
memcpy(qhbuf + 0, &sin->sin_addr, 4);
|
||||
ports = htons(((short)ntohs(sin->sin_port)) - UDP_BASEPORT);
|
||||
memcpy(qhbuf + 4, &ports, 2);
|
||||
dumpraddr(qhbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The multicast address for Descent 2 game announcements.
|
||||
// TODO: Pick a better address for this
|
||||
#define DESCENT2_ANNOUNCE_ADDR inet_addr("239.255.1.2")
|
||||
|
||||
/* Open the socket and subscribe to the multicast session */
|
||||
static int ipx_mcast4_OpenSocket(ipx_socket_t *sk, int port)
|
||||
{
|
||||
u_char loop;
|
||||
struct ip_mreq mreq;
|
||||
struct sockaddr_in sin;
|
||||
int ttl = 128;
|
||||
|
||||
if((sk->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
{
|
||||
sk->fd = -1;
|
||||
FAIL("socket() creation failed on port %d: %m", port);
|
||||
}
|
||||
|
||||
// Bind to the port
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
sin.sin_port = htons(baseport);
|
||||
if (bind(sk->fd, (struct sockaddr *)&sin, sizeof(sin)))
|
||||
{
|
||||
if (closesocket(sk->fd))
|
||||
msg("close() failed during error recovery: %m");
|
||||
sk->fd = -1;
|
||||
FAIL("bind() to UDP port %d failed: %m", baseport);
|
||||
}
|
||||
|
||||
// Set the TTL so the packets can get out of the local network.
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const void*)&ttl, sizeof(ttl)) < 0)
|
||||
FAIL("setsockopt() failed to set TTL to 128");
|
||||
|
||||
// Disable multicast loopback
|
||||
loop = 0;
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void*)&loop, sizeof(loop)) < 0)
|
||||
FAIL("setsockopt() failed to disable multicast loopback: %m");
|
||||
|
||||
// Subscribe to the game announcement address
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_multiaddr.s_addr = DESCENT2_ANNOUNCE_ADDR;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void*)&mreq, sizeof(mreq)) < 0)
|
||||
FAIL("setsockopt() failed to subscribe to the game announcement multicast group");
|
||||
|
||||
// We're not subscribed to a game address yet
|
||||
game_addr.s_addr = 0;
|
||||
|
||||
sk->socket = port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipx_mcast4_CloseSocket(ipx_socket_t *sk)
|
||||
{
|
||||
if(closesocket(sk->fd) < 0)
|
||||
msg("Close failed");
|
||||
sk->fd = -1;
|
||||
}
|
||||
|
||||
static int ipx_mcast4_SendPacket(ipx_socket_t *sk, IPXPacket_t *IPXHeader, u_char *data, int dataLen)
|
||||
{
|
||||
struct sockaddr_in toaddr;
|
||||
int i;
|
||||
|
||||
msg("SendPacket enter, dataLen=%d", dataLen);
|
||||
|
||||
if(dataLen < 0 || dataLen > MAX_PACKETSIZE)
|
||||
return -1;
|
||||
|
||||
toaddr.sin_family = AF_INET;
|
||||
memcpy(&toaddr.sin_addr, IPXHeader->Destination.Node + 0, 4);
|
||||
//toaddr.sin_port = htons(((short)ntohs(*(unsigned short *)(IPXHeader->Destination.Node + 4))) + UDP_BASEPORT);
|
||||
// For now, just use the same port for everything
|
||||
toaddr.sin_port = htons(UDP_BASEPORT);
|
||||
|
||||
// If it's the broadcast address, then we want to send it to the
|
||||
// GAME ANNOUNCEMENT address.
|
||||
// Data to be sent to the GAME has the destination already set by
|
||||
// ipx_mcast4_SendGamePacket
|
||||
if(toaddr.sin_addr.s_addr == INADDR_BROADCAST)
|
||||
toaddr.sin_addr.s_addr = DESCENT2_ANNOUNCE_ADDR;
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
printf(MSGHDR "sendto((%d),Node=[4] %02X %02X,Socket=%02X %02X,s_port=%u,",
|
||||
dataLen,
|
||||
IPXHeader->Destination.Node[4], IPXHeader->Destination.Node[5],
|
||||
IPXHeader->Destination.Socket[0], IPXHeader->Destination.Socket[1],
|
||||
ntohs(toaddr.sin_port));
|
||||
dumpaddr(&toaddr);
|
||||
puts(").");
|
||||
#endif
|
||||
|
||||
i = sendto(sk->fd, data, dataLen, 0, (struct sockaddr *)&toaddr, sizeof(toaddr));
|
||||
return i;
|
||||
}
|
||||
|
||||
static int ipx_mcast4_ReceivePacket(ipx_socket_t *sk, char *outbuf, int outbufsize, struct ipx_recv_data *rd)
|
||||
{
|
||||
int size;
|
||||
struct sockaddr_in fromaddr;
|
||||
int fromaddrsize = sizeof(fromaddr);
|
||||
|
||||
if((size = recvfrom(sk->fd, outbuf, outbufsize, 0, (struct sockaddr*)&fromaddr, &fromaddrsize)) < 0)
|
||||
return -1;
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
printf(MSGHDR "Got packet from ");
|
||||
dumpaddr(&fromaddr);
|
||||
puts("");
|
||||
#endif
|
||||
|
||||
// We have the packet, now fill out the receive data.
|
||||
memset(rd, 0, sizeof(*rd));
|
||||
memcpy(rd->src_node, &fromaddr.sin_addr, 4);
|
||||
// TODO: Include the port like in ipx_udp.c
|
||||
rd->pkt_type = 0;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Handle the netgame aux data
|
||||
* Byte 0 is the protocol version number.
|
||||
* Bytes 1-4 are the IPv4 multicast session to join, in network byte order.
|
||||
*/
|
||||
static int ipx_mcast4_HandleNetgameAuxData(ipx_socket_t *sk, const u_char buf[NETGAME_AUX_SIZE])
|
||||
{
|
||||
// Extract the multicast session and subscribe to it. We should
|
||||
// now be getting packets intended for the players of this game.
|
||||
|
||||
// Note that we stay subscribed to the game announcement session,
|
||||
// so we can reply to game info requests
|
||||
struct ip_mreq mreq;
|
||||
int ttl = 128;
|
||||
|
||||
// Check the protocol version
|
||||
if(buf[0] != IPX_MCAST4_VERSION)
|
||||
{
|
||||
FAIL("mcast4 protocol\nversion mismatch!\nGame version is %02x,\nour version is %02x", buf[0], IPX_MCAST4_VERSION);
|
||||
}
|
||||
|
||||
// Get the multicast session
|
||||
memcpy(&game_addr, buf + 1, sizeof(game_addr));
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
{
|
||||
struct sockaddr_in tmpaddr;
|
||||
tmpaddr.sin_addr = game_addr;
|
||||
tmpaddr.sin_port = 0;
|
||||
|
||||
printf("Handling netgame aux data: Subscribing to ");
|
||||
dumpaddr(&tmpaddr);
|
||||
puts("");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set the TTL so the packets can get out of the local network.
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const void*)&ttl, sizeof(ttl)) < 0)
|
||||
FAIL("setsockopt() failed to set TTL to 128");
|
||||
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_multiaddr = game_addr;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void*)&mreq, sizeof(mreq)) < 0)
|
||||
FAIL("setsockopt() failed to subscribe to the game group");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the netgame aux data.
|
||||
* Byte 0 is the protcol version number.
|
||||
* Bytes 1-4 hold the IPv4 multicast session for the game.
|
||||
*/
|
||||
static void ipx_mcast4_InitNetgameAuxData(ipx_socket_t *sk, u_char buf[NETGAME_AUX_SIZE])
|
||||
{
|
||||
char addr[16];
|
||||
Assert(game_addr.s_addr == 0);
|
||||
|
||||
// The first byte is the version number
|
||||
buf[0] = IPX_MCAST4_VERSION;
|
||||
|
||||
// Generate a random session
|
||||
// game_addr = inet_makeaddr(239*256 + 255, d_rand() % 0xFFFF);
|
||||
sprintf(addr, "%i.%i.%i.%i", 239, 255, d_rand() % 0xFF, d_rand() % 0xFF);
|
||||
game_addr.s_addr = inet_addr(addr);
|
||||
memcpy(buf + 1, &game_addr, sizeof(game_addr));
|
||||
|
||||
// Since we're obviously the hosting machine, subscribe to this address
|
||||
ipx_mcast4_HandleNetgameAuxData(sk, buf);
|
||||
}
|
||||
|
||||
static void ipx_mcast4_HandleLeaveGame(ipx_socket_t *sk)
|
||||
{
|
||||
// We left the game, so unsubscribe from its multicast session
|
||||
struct ip_mreq mreq;
|
||||
|
||||
Assert(game_addr.s_addr != 0);
|
||||
|
||||
#ifdef IPX_MCAST4_DEBUG
|
||||
printf("Unsubscribing from game's multicast group: ");
|
||||
dumpraddr(&game_addr.s_addr);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
mreq.imr_multiaddr = game_addr;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
if(setsockopt(sk->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void*)&mreq, sizeof(mreq)) < 0)
|
||||
msg("setsockopt() failed unsubscribing from previous group!");
|
||||
game_addr.s_addr = 0;
|
||||
}
|
||||
|
||||
// Send a packet to every member of the game. We can just multicast it here.
|
||||
static int ipx_mcast4_SendGamePacket(ipx_socket_t *sk, ubyte *data, int dataLen)
|
||||
{
|
||||
struct sockaddr_in toaddr;
|
||||
int i;
|
||||
|
||||
memset(&toaddr, 0, sizeof(toaddr));
|
||||
toaddr.sin_family = AF_INET;
|
||||
toaddr.sin_addr = game_addr;
|
||||
toaddr.sin_port = htons(UDP_BASEPORT);
|
||||
|
||||
msg("ipx_mcast4_SendGamePacket");
|
||||
|
||||
i = sendto(sk->fd, data, dataLen, 0, (struct sockaddr *)&toaddr, sizeof(toaddr));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// Pull this in from ipx_udp.c since it's the same for us.
|
||||
extern int ipx_udp_GetMyAddress();
|
||||
|
||||
struct ipx_driver ipx_mcast4 = {
|
||||
ipx_udp_GetMyAddress,
|
||||
ipx_mcast4_OpenSocket,
|
||||
ipx_mcast4_CloseSocket,
|
||||
ipx_mcast4_SendPacket,
|
||||
ipx_mcast4_ReceivePacket,
|
||||
ipx_general_PacketReady,
|
||||
ipx_mcast4_InitNetgameAuxData,
|
||||
ipx_mcast4_HandleNetgameAuxData,
|
||||
ipx_mcast4_HandleLeaveGame,
|
||||
ipx_mcast4_SendGamePacket
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx_udp.c,v 1.2 2003-10-08 19:24:17 btb Exp $ */
|
||||
/* $Id: ipx_udp.c,v 1.3 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* IPX driver for native Linux TCP/IP networking (UDP implementation)
|
||||
|
@ -357,7 +357,7 @@ unsigned short ports;
|
|||
/* Startup... Uninteresting parsing...
|
||||
*/
|
||||
|
||||
static int ipx_udp_GetMyAddress(void) {
|
||||
int ipx_udp_GetMyAddress(void) {
|
||||
|
||||
char buf[256];
|
||||
int i;
|
||||
|
@ -614,5 +614,9 @@ struct ipx_driver ipx_udp = {
|
|||
ipx_udp_CloseSocket,
|
||||
ipx_udp_SendPacket,
|
||||
ipx_udp_ReceivePacket,
|
||||
ipx_general_PacketReady
|
||||
ipx_general_PacketReady,
|
||||
NULL, // InitNetgameAuxData
|
||||
NULL, // HandleNetgameAuxData
|
||||
NULL, // HandleLeaveGame
|
||||
NULL // SendGamePacke
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx_win.c,v 1.6 2003-03-19 23:10:34 btb Exp $ */
|
||||
/* $Id: ipx_win.c,v 1.7 2003-10-12 09:17:47 btb Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -205,5 +205,9 @@ struct ipx_driver ipx_win = {
|
|||
ipx_win_CloseSocket,
|
||||
ipx_win_SendPacket,
|
||||
ipx_win_ReceivePacket,
|
||||
ipx_general_PacketReady
|
||||
ipx_general_PacketReady,
|
||||
NULL, // InitNetgameAuxData
|
||||
NULL, // HandleNetgameAuxData
|
||||
NULL, // HandleLeaveGame
|
||||
NULL // SendGamePack
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: winnet.c,v 1.9 2003-10-11 02:36:21 btb Exp $ */
|
||||
/* $Id: winnet.c,v 1.10 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||||
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||||
|
@ -33,6 +33,9 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#include "ipx.h"
|
||||
#include "ipx_drv.h"
|
||||
#include "ipx_udp.h"
|
||||
#include "ipx_mcast4.h"
|
||||
#include "../../main/player.h" /* for Players */
|
||||
#include "../../main/multi.h" /* for NetPlayers */
|
||||
|
||||
extern struct ipx_driver ipx_win;
|
||||
|
||||
|
@ -90,6 +93,7 @@ void arch_ipx_set_driver(int ipx_driver)
|
|||
switch(ipx_driver) {
|
||||
case IPX_DRIVER_IPX: driver = &ipx_win; break;
|
||||
case IPX_DRIVER_UDP: driver = &ipx_udp; break;
|
||||
case IPX_DRIVER_MCAST4: driver = &ipx_mcast4; break;
|
||||
default: Int3();
|
||||
}
|
||||
}
|
||||
|
@ -365,3 +369,51 @@ void ipx_read_network_file(char * filename)
|
|||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// Initalizes the protocol-specific member of the netgame packet.
|
||||
void ipx_init_netgame_aux_data(ubyte buf[])
|
||||
{
|
||||
if(driver->InitNetgameAuxData)
|
||||
driver->InitNetgameAuxData(&ipx_socket_data, buf);
|
||||
}
|
||||
|
||||
// Handles the protocol-specific member of the netgame packet.
|
||||
int ipx_handle_netgame_aux_data(const ubyte buf[])
|
||||
{
|
||||
if(driver->HandleNetgameAuxData)
|
||||
return driver->HandleNetgameAuxData(&ipx_socket_data, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Notifies the protocol that we're done with a particular game
|
||||
void ipx_handle_leave_game()
|
||||
{
|
||||
if(driver->HandleLeaveGame)
|
||||
driver->HandleLeaveGame(&ipx_socket_data);
|
||||
}
|
||||
|
||||
// Send a packet to every member of the game.
|
||||
int ipx_send_game_packet(ubyte *data, int datasize)
|
||||
{
|
||||
if(driver->SendGamePacket) {
|
||||
u_char buf[MAX_IPX_DATA];
|
||||
|
||||
*(uint *)buf = ipx_packetnum++;
|
||||
memcpy(buf + 4, data, datasize);
|
||||
*(uint *)data = ipx_packetnum++;
|
||||
return driver->SendGamePacket(&ipx_socket_data, buf, datasize + 4);
|
||||
} else {
|
||||
// Loop through all the players unicasting the packet.
|
||||
int i;
|
||||
|
||||
//printf("Sending game packet: N_players = %i\n", N_players);
|
||||
|
||||
for(i=0; i<N_players; i++) {
|
||||
if(Players[i].connected && (i != Player_num))
|
||||
ipx_send_packet_data(data, datasize, NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node,Players[i].net_address);
|
||||
}
|
||||
return datasize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ipx.h,v 1.7 2003-10-04 03:18:02 btb Exp $ */
|
||||
/* $Id: ipx.h,v 1.8 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||||
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||||
|
@ -112,6 +112,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#define IPX_DRIVER_IPX 1 // IPX "IPX driver" :-)
|
||||
#define IPX_DRIVER_KALI 2
|
||||
#define IPX_DRIVER_UDP 3 // UDP/IP, user datagrams protocol over the internet
|
||||
#define IPX_DRIVER_MCAST4 4 // UDP/IP, user datagrams protocol over multicast networks
|
||||
|
||||
/* Sets the "IPX driver" (net driver). Takes one of the above consts as argument. */
|
||||
extern void arch_ipx_set_driver(int ipx_driver);
|
||||
|
@ -149,6 +150,15 @@ extern void ipx_send_broadcast_packet_data( ubyte * data, int datasize );
|
|||
extern void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address );
|
||||
extern void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address );
|
||||
|
||||
// Sends a packet to everyone in the game
|
||||
extern int ipx_send_game_packet(ubyte *data, int datasize);
|
||||
|
||||
// Initialize and handle the protocol-specific field of the netgame struct.
|
||||
extern void ipx_init_netgame_aux_data(ubyte data[]);
|
||||
extern int ipx_handle_netgame_aux_data(const ubyte data[]);
|
||||
// Handle disconnecting from the game
|
||||
extern void ipx_handle_leave_game();
|
||||
|
||||
#define IPX_MAX_DATA_SIZE (542) //(546-4)
|
||||
|
||||
extern void ipx_read_user_file(char * filename);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: menu.c,v 1.31 2003-10-11 09:28:38 btb Exp $ */
|
||||
/* $Id: menu.c,v 1.32 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||||
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||||
|
@ -131,6 +131,8 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#define MENU_JOIN_UDP_NETGAME 31
|
||||
#define MENU_START_KALI_NETGAME 32 // Kali support copied from d1x
|
||||
#define MENU_JOIN_KALI_NETGAME 33
|
||||
#define MENU_START_MCAST4_NETGAME 34 // UDP/IP over multicast networks
|
||||
#define MENU_JOIN_MCAST4_NETGAME 35
|
||||
|
||||
//ADD_ITEM("Start netgame...", MENU_START_NETGAME, -1 );
|
||||
//ADD_ITEM("Send net message...", MENU_SEND_NET_MESSAGE, -1 );
|
||||
|
@ -461,6 +463,8 @@ void do_option ( int select)
|
|||
case MENU_JOIN_UDP_NETGAME:
|
||||
case MENU_START_KALI_NETGAME:
|
||||
case MENU_JOIN_KALI_NETGAME:
|
||||
case MENU_START_MCAST4_NETGAME:
|
||||
case MENU_JOIN_MCAST4_NETGAME:
|
||||
load_mission(Builtin_mission_num);
|
||||
#ifdef MACINTOSH
|
||||
Network_game_type = IPX_GAME;
|
||||
|
@ -470,6 +474,7 @@ void do_option ( int select)
|
|||
case MENU_START_IPX_NETGAME: ipx_set_driver(IPX_DRIVER_IPX); break;
|
||||
case MENU_START_UDP_NETGAME: ipx_set_driver(IPX_DRIVER_UDP); break;
|
||||
case MENU_START_KALI_NETGAME: ipx_set_driver(IPX_DRIVER_KALI); break;
|
||||
case MENU_START_MCAST4_NETGAME: ipx_set_driver(IPX_DRIVER_MCAST4); break;
|
||||
default: Int3();
|
||||
}
|
||||
|
||||
|
@ -1726,6 +1731,8 @@ void do_multi_player_menu()
|
|||
//ADD_ITEM(TXT_JOIN_TCP_NET_GAME, MENU_JOIN_TCP_NETGAME, -1);
|
||||
ADD_ITEM("Start UDP/IP Netgame", MENU_START_UDP_NETGAME, -1);
|
||||
ADD_ITEM("Join UDP/IP Netgame\n", MENU_JOIN_UDP_NETGAME, -1);
|
||||
ADD_ITEM("Start Multicast UDP/IP Netgame", MENU_START_MCAST4_NETGAME, -1);
|
||||
ADD_ITEM("Join Multicast UDP/IP Netgame\n", MENU_JOIN_MCAST4_NETGAME, -1);
|
||||
#ifdef __unix__
|
||||
ADD_ITEM("Start Kali Netgame", MENU_START_KALI_NETGAME, -1);
|
||||
ADD_ITEM("Join Kali Netgame\n", MENU_JOIN_KALI_NETGAME, -1);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: multi.h,v 1.11 2003-10-08 17:09:48 schaffner Exp $ */
|
||||
/* $Id: multi.h,v 1.12 2003-10-12 09:17:47 btb Exp $ */
|
||||
/*
|
||||
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||||
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||||
|
@ -504,6 +504,7 @@ extern bitmap_index multi_player_textures[MAX_NUM_NET_PLAYERS][N_PLAYER_SHIP_TEX
|
|||
#define NETGAME_FLAG_REALLY_FORMING 64
|
||||
|
||||
#define NETGAME_NAME_LEN 15
|
||||
#define NETGAME_AUX_SIZE 20 // Amount of extra data for the network protocol to store in the netgame packet
|
||||
|
||||
enum comp_type {DOS,WIN_32,WIN_95,MAC} __pack__ ;
|
||||
|
||||
|
@ -653,6 +654,7 @@ typedef struct netgame_info {
|
|||
ubyte player_flags[MAX_PLAYERS];
|
||||
short PacketsPerSec;
|
||||
ubyte ShortPackets;
|
||||
ubyte AuxData[NETGAME_AUX_SIZE]; // Storage for protocol-specific data (e.g., multicast session and port)
|
||||
|
||||
} __pack__ netgame_info;
|
||||
|
||||
|
@ -666,5 +668,4 @@ void change_playernum_to(int new_pnum);
|
|||
#define MISSILE_ADJUST 100
|
||||
#define FLARE_ADJUST 127
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* _MULTI_H */
|
||||
|
|
Loading…
Reference in a new issue