Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
mangler.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19
20#include <iostream.h>
21#include <signal.h>
22#ifdef _WINDOWS
23#include <process.h> // *MUST* be included before ANY Wnet/Wlib headers if _REENTRANT is defined
24#endif
25
26#include "mangler.h"
27#include "crc.h"
28#include "endian.h"
29
30#include <configfile.h>
31#include "threadfac.h"
32
33#include "xtime.h"
34#include <filed.h>
35#include <wstring.h>
36#include <wdebug.h>
37#include <udp.h>
38
39void DisplayHelp(const char *prog)
40{
41 cout << "Usage: " << prog << " <config file>" << endl;
42 exit(0);
43}
44
45int main(int argc, char **argv)
46{
47 ConfigFile config;
48 FILE* conf;
49
50 if( argc <= 1 )
51 {
52 // No args - use a default config file
53 if ((conf = fopen("mangler.cfg", "r")) == NULL) {
54 cout << "Cannot open mangler.cfg for reading." << endl;
55 DisplayHelp(argv[0]);
56 }
57 config.readFile(conf);
58 fclose(conf);
59 }
60 else if( argc == 2 && (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "?") == 0 ||
61 strcmp(argv[1], "-h") == 0) )
62 DisplayHelp(argv[0]);
63 else if( argc == 2 )
64 {
65 // Use a user-supplied config file
66 if ((conf = fopen(argv[1], "r")) == NULL) {
67 cout << "Cannot open " << argv[1] << " for reading." << endl;
68 DisplayHelp(argv[0]);
69 }
70 config.readFile(conf);
71 fclose(conf);
72 }
73
74 // ----- LOGGING -----
75 // Setup debugging & logging output
76 Wstring output_file("mangler.log");
77 config.getString("LOGFILE", output_file);
78 Wstring backup_file;
79 backup_file = output_file;
80 backup_file += ".bak";
81 rename(output_file.get(),backup_file.get()); // save the old file
82 FileD output_device(output_file.get());
84 DBGMSG("DBG working...");
85 INFMSG("INF working...");
86 WRNMSG("WRN working...");
87
88 if (htonl(0x12345678) == 0x12345678)
89 {
90 INFMSG("Host is network-byte-order");
91 }
92 else
93 {
94 INFMSG("Host is Intel-byte-order");
95 }
96
97
98 // ----- Initialize Winsock -----
99#ifdef _WINDOWS
100 WORD verReq = MAKEWORD(2, 2);
101 WSADATA wsadata;
102
103 int err = WSAStartup(verReq, &wsadata);
104 if (err != 0) {
105 ERRMSG("Winsock Init failed.");
106 return 1;
107 }
108
109 if ((LOBYTE(wsadata.wVersion) != 2) || (HIBYTE(wsadata.wVersion) !=2)) {
110 ERRMSG("Winsock DLL is not 2.2");
111 WSACleanup();
112 ERRMSG("Winsock Init failed.");
113 return 1;
114 }
115 INFMSG("Winsock Init done.");
116#endif
117
118
119 // Set up a UDP listener
120 uint8 *buff=new uint8[1024];
121 int retval;
122 UDP udp;
123 UDP udp2;
124 UDP udp3;
125 UDP udp4;
126 int port = 4321;
127 config.getInt("PORT", port);
128 uint8 blitz = 0;
129
130 uint32 localIP = 0;
131 Wstring hostIPStr = "";
132 config.getString("IP", hostIPStr);
133 if (hostIPStr.length())
134 {
135 INFMSG("Binding to "<<hostIPStr.get()<<":"<<port<<"-"<<(port+3));
136 localIP = ntohl(inet_addr(hostIPStr.get()));
137 }
138 else
139 {
140 INFMSG("Binding to localhost:"<<port<<"-"<<(port+3));
141 }
142
143 retval = udp.Bind(localIP,(uint16)port);
144 retval |= udp2.Bind(localIP,(uint16)port+1);
145 retval |= udp3.Bind(localIP,(uint16)port+2);
146 retval |= udp4.Bind(localIP,(uint16)port+3);
147 if (retval != 0)
148 {
149 ERRMSG("Couldn't bind - error " << retval);
150 exit(1);
151 }
152
153 unsigned char buf[1024];
154 struct sockaddr_in addr;
155 int packet_size = sizeof(ManglerData);
156 INFMSG("sizeof(packet) == " << packet_size);
157 unsigned char *theAddr;
158 fd_set fdset;
159 while (1)
160 {
161 retval = udp.Wait(15, 0, fdset);
162 if (!retval)
163 continue;
164
165 //DBGMSG("Wait returned " << retval);
166 retval = udp.Read(buf, packet_size, &addr); // Wait until there is something on the socket
167 if (retval > 0)
168 {
169 ManglerData *packet = (ManglerData *)buf;
170 theAddr = (unsigned char *)&(addr.sin_addr.s_addr);
171 if (retval != packet_size)
172 {
173 WRNMSG("Recieved mis-sized packet (" << retval << " bytes) from " << theAddr[0] << "." << theAddr[1] << "." << theAddr[2] << "." << theAddr[3] << ":" << addr.sin_port);
174 }
175 else
176 {
177 if (!Passes_CRC_Check(buf, packet_size))
178 {
179 WRNMSG("Recieved a bad packet - good length!");
180 continue;
181 }
182 packet->NetCommandType = 44;
183 packet->MyMangledPortNumber = addr.sin_port; // not changing to host order, cause its in network byte order now, and the game will expect it to stay that way.
184 packet->MyMangledAddress[0] = theAddr[0];
185 packet->MyMangledAddress[1] = theAddr[1];
186 packet->MyMangledAddress[2] = theAddr[2];
187 packet->MyMangledAddress[3] = theAddr[3];
188 blitz = packet->BlitzMe;
189 INFMSG("Packet ID = " << packet->packetID);
190 Build_Packet_CRC(buf, packet_size);
191 udp.Write(buf,packet_size,ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
192 INFMSG("Saw " << (int)theAddr[0] << "." << (int)theAddr[1] << "." << (int)theAddr[2] << "." << (int)theAddr[3] << ":" << ntohs(addr.sin_port) << ((blitz)?" Blitzed":"") );
193
194 if (blitz)
195 {
196 udp2.Write(buf,packet_size,ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port)+1);
197 udp3.Write(buf,packet_size,ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port)+2);
198 udp4.Write(buf,packet_size,ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port)+3);
199 }
200 }
201 }
202 }
203
204
205 return 0;
206}
207
208
#define NULL
Definition BaseType.h:92
#define INFMSG(X)
Definition wdebug.h:64
#define ERRMSG(X)
Definition wdebug.h:86
#define WRNMSG(X)
Definition wdebug.h:75
#define DBGMSG(X)
Definition wdebug.h:128
unsigned short uint16
Definition bittype.h:45
unsigned short WORD
Definition bittype.h:58
unsigned long uint32
Definition bittype.h:46
unsigned char uint8
Definition bittype.h:44
bool Passes_CRC_Check(unsigned char *buf, int len)
Definition crc.cpp:137
void Build_Packet_CRC(unsigned char *buf, int len)
Definition crc.cpp:80
bit8 getInt(IN Wstring &key, OUT sint32 &value)
bit8 readFile(IN FILE *config)
bit8 getString(IN Wstring &key, OUT Wstring &value)
Definition filed.h:25
static int setAllStreams(OutputDevice *device)
Definition wdebug.cpp:45
Definition udp.h:66
Int Bind(UnsignedInt IP, UnsignedShort port)
Definition udp.cpp:153
Int Write(const unsigned char *msg, UnsignedInt len, UnsignedInt IP, UnsignedShort port)
Definition udp.cpp:238
Int Read(unsigned char *msg, UnsignedInt len, sockaddr_in *from)
Definition udp.cpp:270
int Wait(sint32 sec, sint32 usec, fd_set &returnSet)
Definition udp.cpp:227
uint32 length(void)
Definition wstring.cpp:350
char * get(void)
Definition wstring.cpp:336
void main(void)
Definition test1.cpp:47
void DisplayHelp(const char *prog)
Definition mangler.cpp:39
OutputDevice * output_device
Definition main.cpp:59
unsigned char MyMangledAddress[4]
unsigned short MyMangledPortNumber
unsigned char NetCommandType
unsigned char BlitzMe