2 * Netris -- A free networked version of T*tris
3 * Copyright (C) 1994,1995,1996 Mark H. Weaver <mhw@netris.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * $Id: inet.c,v 1.18 1996/02/09 08:22:13 mhw Exp $
23 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
32 #define HEADER_SIZE sizeof(netint2[2])
33 #define HEADER_SIZE3 sizeof(netint4[3])
35 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
37 EventGenRec netGen[MAX_SCREENS] = {
38 { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE3 } };
40 //static char netBuf[64];
41 //static int netBufSize, netBufGoal = HEADER_SIZE3;
43 ExtFunc void make_netGen(void)
47 for (i = 1; i <= MAX_SCREENS; i++)
48 memcpy(netGen+i, &netGen[0], sizeof(EventGenRec));
52 ExtFunc int InitiateConnection(char *hostStr, char *portStr)
54 struct sockaddr_in addr;
61 port = atoi(portStr); /* XXX Error checking */
64 host = gethostbyname(hostStr);
67 assert(host->h_addrtype == AF_INET);
69 memset(&addr, 0, sizeof(addr));
70 addr.sin_family = host->h_addrtype;
71 memcpy(&addr.sin_addr, host->h_addr, host->h_length);
72 addr.sin_port = htons(port);
73 if ((netGen[0].fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
75 if (connect(netGen[0].fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
76 if (errno != ECONNREFUSED)
82 AddEventGen(&netGen[0]);
85 } //InitiateConnection
87 ExtFunc void HandShake(void)
92 netint4 versiondata[2];
93 versiondata[0] = hton4(MAJOR_VERSION);
94 versiondata[1] = hton4(PROTOCOL_VERSION);
95 SendPacket(0, NP_hello, sizeof(versiondata), versiondata);
99 if (WaitMyEvent(&event, EM_net) == E_net)
100 switch (event.u.net.type) {
103 me = event.u.net.uid;
104 memcpy(&Players[me], &Players[0], sizeof(Player));
105 fprintf(stderr, "Accepted (%s) as #%d (%s)\n",
106 event.u.net.data, me, Players[me].name);
107 SendPacket(0, NP_newPlayer,
108 sizeof(Player) - sizeof(Players[me].host) - sizeof(Players[me].spy),
114 fprintf(stderr, ": %d\n", event.type);
120 memcpy(&Players[event.u.net.uid],
121 event.u.net.data, event.u.net.size);
122 fprintf(stderr, "Receiving player #%d (%s)\n",
123 event.u.net.uid, Players[event.u.net.uid].name);
128 fprintf(stderr, "Rejected by server: %s\n", event.u.net.data);
135 fatal("Hm, the party apparantly ended prematurely.");
137 while (event.u.net.type != NP_goAhead);
140 // receive seed, initspeed
142 // receive Players[*]
150 if (protocolVersion >= 3)
153 len = sizeof(netint4[2]);
154 if ((Players[0].flags & SCF_setSeed))
160 data[0] = hton4(Players[0].flags);
161 data[1] = hton4(seed);
162 data[2] = hton4(Game.initspeed);
163 SendPackets(0, NP_startConn, len, data);
164 if (WaitMyEvent(&event, EM_net) != E_net ||
165 event.u.net.type != NP_startConn)
166 fatal("Network negotiation failed");
167 memcpy(data, event.u.net.data, len);
168 Players[1].flags = ntoh4(data[0]);
169 seed = ntoh4(data[1]);
171 if ((Players[0].flags & SCF_setSeed) != (Players[1].flags & SCF_setSeed))
172 fatal("If one player sets the random number seed, "
174 if ((Players[0].flags & SCF_setSeed) && seed != Game.seed)
175 fatal("Both players have set the random number seed, "
176 "and they are unequal.");
177 if (protocolVersion >= 3 && Game.initspeed != ntoh4(data[2]))
178 fatal("Your opponent is using a different step-down "
179 "interval (-i).\nYou must both use the same one.");
184 // SendPackets(0, NP_initData, strlen(Players[0].name) + 1, Players[0].name);
187 if (WaitMyEvent(&event, EM_net) != E_net ||
188 event.u.net.type != NP_userName)
189 fatal("Network negotiation failed");
190 strncpy(Players[1].name, event.u.net.data,
191 sizeof(Players[1].name) - 1);
192 Players[1].name[sizeof(Players[1].name)-1] = 0;
193 for (i = 0; Players[1].name[i]; ++i)
194 if (!isprint(Players[1].name[i]))
195 Players[1].name[i] = '?';
196 for (i = 0; Players[1].host[i]; ++i)
197 if (!isprint(Players[1].host[i]))
198 Players[1].host[i] = '?';
202 ExtFunc void CheckNetConn(void)
207 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
210 short uid, type, size;
211 netint4 *data = (netint4*)&(gen->buf);
213 result = MyRead(gen->fd, gen->buf + gen->bufSize,
214 gen->bufGoal - gen->bufSize);
220 gen->bufSize += result;
221 if (gen->bufSize < gen->bufGoal)
223 // *ugly* memcpy(data, gen->buf, sizeof(data));
224 uid = ntoh4(data[0]);
225 type = ntoh4(data[1]);
226 size = ntoh4(data[2]);
228 if (gen->bufSize < gen->bufGoal)
231 gen->bufGoal = HEADER_SIZE3;
232 event->u.net.sender = gen->player;
233 event->u.net.uid = uid;
234 event->u.net.type = type;
235 event->u.net.size = size - HEADER_SIZE3;
236 event->u.net.data = gen->buf + HEADER_SIZE3;
237 if (type == NP_endConn) {
238 fprintf(stderr, "Close connection\n");
244 ExtFunc void SendPacket(short uid, NetPacketType type, int size, void *data)
245 { //send shit to server
248 header[0] = hton4(uid);
249 header[1] = hton4(type);
250 header[2] = hton4(size + HEADER_SIZE3);
251 if (MyWrite(netGen[0].fd, header, HEADER_SIZE3) != HEADER_SIZE3)
252 die("write (header)");
253 if (size > 0 && data && MyWrite(netGen[0].fd, data, size) != size)
257 ExtFunc void CloseNet(void)
258 { //kick some connection's ass!
261 if (netGen[0].fd >= 0) {
262 SendPacket(0, NP_endConn, 0, NULL);
267 RemoveEventGen(&netGen[0]);