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])
34 static MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
37 static EventGenRec netGen = { NULL, 0, FT_read, -1, NetGenFunc, EM_net };
39 static char netBuf[64];
40 static int netBufSize, netBufGoal = HEADER_SIZE;
41 static int isServer, lostConn, gotEndConn;
43 ExtFunc void InitNet(void)
50 ExtFunc int WaitForConnection(char *portStr)
52 struct sockaddr_in addr;
61 port = atoi(portStr); /* XXX Error checking */
64 memset(&addr, 0, sizeof(addr));
65 addr.sin_family = AF_INET;
66 addr.sin_addr.s_addr = htonl(INADDR_ANY);
67 addr.sin_port = htons(port);
68 sockListen = socket(AF_INET, SOCK_STREAM, 0);
72 setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
73 (void *)&val1, sizeof(val1));
74 if (bind(sockListen, (struct sockaddr *)&addr, sizeof(addr)) < 0)
76 if (listen(sockListen, 1) < 0)
78 addrLen = sizeof(addr);
79 sock = accept(sockListen, (struct sockaddr *)&addr, &addrLen);
85 setsockopt(sock, SOL_SOCKET, SO_LINGER,
86 (void *)&val2, sizeof(val2));
88 strcpy(opponentHost, "???");
89 if (addr.sin_family == AF_INET) {
90 host = gethostbyaddr((void *)&addr.sin_addr,
91 sizeof(struct in_addr), AF_INET);
93 strncpy(opponentHost, host->h_name, sizeof(opponentHost)-1);
94 opponentHost[sizeof(opponentHost)-1] = 0;
102 ExtFunc int InitiateConnection(char *hostStr, char *portStr)
104 struct sockaddr_in addr;
105 struct hostent *host;
110 port = atoi(portStr); /* XXX Error checking */
113 host = gethostbyname(hostStr);
115 die("gethostbyname");
116 assert(host->h_addrtype == AF_INET);
117 strncpy(opponentHost, host->h_name, sizeof(opponentHost)-1);
118 opponentHost[sizeof(opponentHost)-1] = 0;
120 memset(&addr, 0, sizeof(addr));
121 addr.sin_family = host->h_addrtype;
122 memcpy(&addr.sin_addr, host->h_addr, host->h_length);
123 addr.sin_port = htons(port);
124 mySock = socket(AF_INET, SOCK_STREAM, 0);
127 if (connect(mySock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
128 if (errno != ECONNREFUSED)
134 netGen.fd = sock = mySock;
135 AddEventGen(&netGen);
139 static MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
145 result = MyRead(sock, netBuf + netBufSize, netBufGoal - netBufSize);
150 netBufSize += result;
151 if (netBufSize < netBufGoal)
153 memcpy(data, netBuf, sizeof(data));
154 type = ntoh2(data[0]);
155 size = ntoh2(data[1]);
156 if (size >= sizeof(netBuf))
157 fatal("Received an invalid packet (too large), possibly an attempt\n"
158 " to exploit a vulnerability in versions before 0.52 !");
160 if (netBufSize < netBufGoal)
163 netBufGoal = HEADER_SIZE;
164 event->u.net.type = type;
165 event->u.net.size = size - HEADER_SIZE;
166 event->u.net.data = netBuf + HEADER_SIZE;
167 if (type == NP_endConn) {
171 else if (type == NP_byeBye) {
178 ExtFunc void CheckNetConn(void)
182 ExtFunc void SendPacket(NetPacketType type, int size, void *data)
186 header[0] = hton2(type);
187 header[1] = hton2(size + HEADER_SIZE);
188 if (MyWrite(sock, header, HEADER_SIZE) != HEADER_SIZE)
190 if (size > 0 && data && MyWrite(sock, data, size) != size)
194 ExtFunc void CloseNet(void)
200 SendPacket(NP_endConn, 0, NULL);
203 WaitMyEvent(&event, EM_net);
207 WaitMyEvent(&event, EM_net);
208 SendPacket(NP_byeBye, 0, NULL);
215 RemoveEventGen(&netGen);