unofficial version 0.6: first major updates
[netris.git] / inet.c
1 /*
2  * Netris -- A free networked version of T*tris
3  * Copyright (C) 1994,1995,1996  Mark H. Weaver <mhw@netris.org>
4  * 
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.
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, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * $Id: inet.c,v 1.18 1996/02/09 08:22:13 mhw Exp $
20  */
21
22 #include "netris.h"
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <netdb.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #define HEADER_SIZE sizeof(netint2[2])
33 #define HEADER_SIZE3 sizeof(netint4[3])
34
35 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
36
37 EventGenRec netGen[MAX_SCREENS] = {
38         { NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE3 } };
39
40 //static char netBuf[64];
41 //static int netBufSize, netBufGoal = HEADER_SIZE3;
42
43 ExtFunc void make_netGen(void)
44 {
45         int i;
46
47         for (i = 1; i <= MAX_SCREENS; i++)
48                 memcpy(netGen+i, &netGen[0], sizeof(EventGenRec));
49 } //Make_netGen
50
51
52 ExtFunc int InitiateConnection(char *hostStr, char *portStr)
53 { //connect to host
54         struct sockaddr_in addr;
55         struct hostent *host;
56         short port;
57
58 //      make_netGen();
59         AtExit(CloseNet);
60         if (portStr)
61                 port = atoi(portStr);   /* XXX Error checking */
62         else
63                 port = DEFAULT_PORT;
64         host = gethostbyname(hostStr);
65         if (!host)
66                 die("gethostbyname");
67         assert(host->h_addrtype == AF_INET);
68  again:
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)
74                 die("socket");
75         if (connect(netGen[0].fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
76                 if (errno != ECONNREFUSED)
77                         die("connect");
78                 close(netGen[0].fd);
79                 sleep(1);
80                 goto again;
81         }
82         AddEventGen(&netGen[0]);
83         totalPlayers = 0;
84         return 0;
85 } //InitiateConnection
86
87 ExtFunc void HandShake(void)
88 { //talk to your host
89         MyEvent event;
90
91         {
92                 netint4 versiondata[2];
93                 versiondata[0] = hton4(MAJOR_VERSION);
94                 versiondata[1] = hton4(PROTOCOL_VERSION);
95                 SendPacket(0, NP_hello, sizeof(versiondata), versiondata);
96         }
97
98         do {
99                 if (WaitMyEvent(&event, EM_net) == E_net)
100                 switch (event.u.net.type) {
101                         case NP_hello:
102                         {
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),
109                                         &Players[me]);
110                                 break;
111                         }
112                         case NP_gamedata:
113                         {
114                                 fprintf(stderr, ": %d\n", event.type);
115                                 break;
116                         }
117                         case NP_newPlayer:
118                         {
119                                 totalPlayers++;
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);
124                                 break;
125                         }
126                         case NP_error:
127                         {
128                                 fprintf(stderr, "Rejected by server: %s\n", event.u.net.data);
129                                 exit(1);
130                         }
131                         default:
132                                 break;
133                 }
134                 else
135                         fatal("Hm, the party apparantly ended prematurely.");
136         }
137         while (event.u.net.type != NP_goAhead);
138
139         // send Players[0]
140         // receive seed, initspeed
141                 // receive #players
142                 // receive Players[*]
143
144         /*
145                         {
146                         netint4 data[3];
147                         int len;
148                         int seed;
149
150                         if (protocolVersion >= 3)
151                                 len = sizeof(data);
152                         else
153                                 len = sizeof(netint4[2]);
154                         if ((Players[0].flags & SCF_setSeed))
155                                 seed = Game.seed;
156                         else
157                                 seed = time(0);
158                         if (waitConn)
159                                 SRandom(seed);
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]);
170                         if (initConn) {
171                                 if ((Players[0].flags & SCF_setSeed) != (Players[1].flags & SCF_setSeed))
172                                         fatal("If one player sets the random number seed, "
173                                                         "both must.");
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.");
180                                 SRandom(seed);
181                         }
182                 }
183                 */
184 //              SendPackets(0, NP_initData, strlen(Players[0].name) + 1, Players[0].name);
185
186 /*
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] = '?';
199 */
200 } //HandShake
201
202 ExtFunc void CheckNetConn(void)
203 { //am I necessary?
204 }
205
206
207 ExtFunc MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
208 { //receive
209         int result;
210         short uid, type, size;
211         netint4 *data = (netint4*)&(gen->buf);
212
213         result = MyRead(gen->fd, gen->buf + gen->bufSize,
214                 gen->bufGoal - gen->bufSize);
215         if (result < 0) {
216                 close(gen->fd);
217                 gen->fd = -1;
218                 return E_lostConn;
219         }
220         gen->bufSize += result;
221         if (gen->bufSize < gen->bufGoal)
222                 return E_none;
223         // *ugly* memcpy(data, gen->buf, sizeof(data));
224         uid = ntoh4(data[0]);
225         type = ntoh4(data[1]);
226         size = ntoh4(data[2]);
227         gen->bufGoal = size;
228         if (gen->bufSize < gen->bufGoal)
229                 return E_none;
230         gen->bufSize = 0;
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");
239                 return E_lostConn;
240         }
241         return E_net;
242 } //NetGenFunc
243
244 ExtFunc void SendPacket(short uid, NetPacketType type, int size, void *data)
245 { //send shit to server
246         netint4 header[3];
247
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)
254                 die("write");
255 } //SendPacket
256
257 ExtFunc void CloseNet(void)
258 { //kick some connection's ass!
259         MyEvent event;
260
261         if (netGen[0].fd >= 0) {
262                 SendPacket(0, NP_endConn, 0, NULL);
263                 close(netGen[0].fd);
264                 netGen[0].fd = -1;
265         }
266         if (netGen[0].next)
267                 RemoveEventGen(&netGen[0]);
268 } //CloseNet
269
270 /*
271  * vi: ts=4 ai
272  * vim: noai si
273  */