code duplication
[netris.git] / inet.c
diff --git a/inet.c b/inet.c
index dbfe7484f0d8b9bb2a65f956ce9afc7e9d979bb5..33d49b05c0a767b826c951c031bc1caea82b76da 100644 (file)
--- a/inet.c
+++ b/inet.c
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: inet.c,v 1.18 1996/02/09 08:22:13 mhw Exp $
  */
 
 #include "netris.h"
+
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <netdb.h>
 #include <string.h>
 #include <errno.h>
+#include <setjmp.h>
+
+#include "inet.h"
 
 #define HEADER_SIZE sizeof(netint2[2])
+#define HEADER_SIZE3 sizeof(netint4[3])
 
 static MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event);
+static EventGenRec netGen = {
+       NULL, 0, FT_read, -1, NetGenFunc, EM_net, 0, "\0", 0, HEADER_SIZE3
+};
 
-static int sock = -1;
-static EventGenRec netGen = { NULL, 0, FT_read, -1, NetGenFunc, EM_net };
-
-static char netBuf[64];
-static int netBufSize, netBufGoal = HEADER_SIZE;
-static int isServer, lostConn, gotEndConn;
 
-ExtFunc void InitNet(void)
-{
-       AtExit(CloseNet);
-}
+static sigjmp_buf close_env;
 
-ExtFunc int WaitForConnection(char *portStr)
+static void CatchInt(int sig)
 {
-       struct sockaddr_in addr;
-       struct hostent *host;
-       int sockListen;
-       int addrLen;
-       short port;
-       int val1;
-       struct linger val2;
-
-       if (portStr)
-               port = atoi(portStr);   /* XXX Error checking */
-       else
-               port = DEFAULT_PORT;
-       memset(&addr, 0, sizeof(addr));
-       addr.sin_family = AF_INET;
-       addr.sin_addr.s_addr = htonl(INADDR_ANY);
-       addr.sin_port = htons(port);
-       sockListen = socket(AF_INET, SOCK_STREAM, 0);
-       if (sockListen < 0)
-               die("socket");
-       val1 = 1;
-       setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
-                       (void *)&val1, sizeof(val1));
-       if (bind(sockListen, (struct sockaddr *)&addr, sizeof(addr)) < 0)
-               die("bind");
-       if (listen(sockListen, 1) < 0)
-               die("listen");
-       addrLen = sizeof(addr);
-       sock = accept(sockListen, (struct sockaddr *)&addr, &addrLen);
-       if (sock < 0)
-               die("accept");
-       close(sockListen);
-       val2.l_onoff = 1;
-       val2.l_linger = 0;
-       setsockopt(sock, SOL_SOCKET, SO_LINGER,
-                       (void *)&val2, sizeof(val2));
-       netGen.fd = sock;
-       strcpy(opponentHost, "???");
-       if (addr.sin_family == AF_INET) {
-               host = gethostbyaddr((void *)&addr.sin_addr,
-                               sizeof(struct in_addr), AF_INET);
-               if (host) {
-                       strncpy(opponentHost, host->h_name, sizeof(opponentHost)-1);
-                       opponentHost[sizeof(opponentHost)-1] = 0;
-               }
-       }
-       AddEventGen(&netGen);
-       isServer = 1;
-       return 0;
+       siglongjmp(close_env, 1);
 }
 
-ExtFunc int InitiateConnection(char *hostStr, char *portStr)
-{
+int InitiateConnection(char *hostStr, short port)
+{ //connect to host
        struct sockaddr_in addr;
        struct hostent *host;
-       short port;
-       int mySock;
 
-       if (portStr)
-               port = atoi(portStr);   /* XXX Error checking */
-       else
-               port = DEFAULT_PORT;
+       if (sigsetjmp(close_env, 1))
+               exit(0);
+       signal(SIGINT, CatchInt);  //handle exit (^C)
+       AtExit(CloseNet);
        host = gethostbyname(hostStr);
        if (!host)
                die("gethostbyname");
        assert(host->h_addrtype == AF_INET);
-       strncpy(opponentHost, host->h_name, sizeof(opponentHost)-1);
-       opponentHost[sizeof(opponentHost)-1] = 0;
  again:
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = host->h_addrtype;
        memcpy(&addr.sin_addr, host->h_addr, host->h_length);
        addr.sin_port = htons(port);
-       mySock = socket(AF_INET, SOCK_STREAM, 0);
-       if (mySock < 0)
+       if ((netGen.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                die("socket");
-       if (connect(mySock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+       if (connect(netGen.fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
                if (errno != ECONNREFUSED)
                        die("connect");
-               close(mySock);
+               close(netGen.fd);
                sleep(1);
                goto again;
        }
-       netGen.fd = sock = mySock;
        AddEventGen(&netGen);
        return 0;
 }
 
+void HandShake(void)
+{ //talk to your host
+       MyEvent event;
+
+       {
+               netint4 versiondata[2];
+               versiondata[0] = hton4(MAJOR_VERSION);
+               versiondata[1] = hton4(PROTOCOL_VERSION);
+               SendPacket(0, NP_hello, sizeof(versiondata), versiondata);
+       }
+
+       do {
+               if (WaitMyEvent(&event, EM_net) == E_net)
+                       switch (event.u.net.type) {
+                       case NP_hello:
+                       {
+                               me = event.u.net.uid;
+                               memcpy(&Players[me], &Players[0], sizeof(player_t));
+                               fprintf(stderr, "Accepted (%s) as #%d (%s)\n",
+                                       event.u.net.data, me, Players[me].name);
+                               SendPacket(0, NP_newPlayer,
+                                       sizeof(player_t) - sizeof(Players[me].host),
+                                       &Players[me]);
+                               break;
+                       }
+                       case NP_team:
+                       { //receive your teamnumber
+                               memcpy(&Players[event.u.net.uid].team, event.u.net.data,
+                                       event.u.net.size);
+                               break;
+                       } //NP_team
+                       case NP_gamedata:
+                       {
+                               static struct {
+                                       int playerflags;
+                                       int gravity;     //1
+                                       int started;     //2
+                                       int continuous;  //3
+                                       long seed;       //4
+                                       float shapes[7];
+                                       int initspeed;   //5
+                               } data;
+
+                               memcpy(&data, event.u.net.data, event.u.net.size);
+                               memcpy(&Players[me].flags, &data, sizeof(data.playerflags));
+                               memcpy(&Players[me].flags, &data, sizeof(data.playerflags));
+                               memcpy(&Game.gravity, &data.gravity,
+                                       sizeof(data) - sizeof(data.playerflags));
+                               break;
+                       } //NP_gamedata
+                       case NP_error:
+                       {
+                               fprintf(stderr, "Rejected by server: %s\n", event.u.net.data);
+                               exit(1);
+                       } //NP_error
+                       default:
+                               break;
+                       }
+               else
+                       fatal("Hm, the party apparantly ended prematurely.");
+       } while (event.u.net.type != NP_gamedata);
+}
+
+
 static MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event)
-{
+{ //receive
        int result;
-       short type, size;
-       netint2 data[2];
+       short uid, type, size;
+       netint4 *data = (netint4*)&(gen->buf);
 
-       result = MyRead(sock, netBuf + netBufSize, netBufGoal - netBufSize);
+       result = MyRead(gen->fd, gen->buf + gen->bufSize,
+               gen->bufGoal - gen->bufSize);
        if (result < 0) {
-               lostConn = 1;
+               close(gen->fd);
+               gen->fd = -1;
                return E_lostConn;
        }
-       netBufSize += result;
-       if (netBufSize < netBufGoal)
+       gen->bufSize += result;
+       if (gen->bufSize < gen->bufGoal)
                return E_none;
-       memcpy(data, netBuf, sizeof(data));
-       type = ntoh2(data[0]);
-       size = ntoh2(data[1]);
-       netBufGoal = size;
-       if (netBufSize < netBufGoal)
+       // *ugly* memcpy(data, gen->buf, sizeof(data));
+       uid = ntoh4(data[0]);
+       type = ntoh4(data[1]);
+       size = ntoh4(data[2]);
+       gen->bufGoal = size;
+       if (gen->bufSize < gen->bufGoal)
                return E_none;
-       netBufSize = 0;
-       netBufGoal = HEADER_SIZE;
+       gen->bufSize = 0;
+       gen->bufGoal = HEADER_SIZE3;
+       event->u.net.sender = gen->player;
+       event->u.net.uid = uid;
        event->u.net.type = type;
-       event->u.net.size = size - HEADER_SIZE;
-       event->u.net.data = netBuf + HEADER_SIZE;
-       if (type == NP_endConn) {
-               gotEndConn = 1;
-               return E_lostConn;
-       }
-       else if (type == NP_byeBye) {
-               lostConn = 1;
-               return E_lostConn;
-       }
+       event->u.net.size = size - HEADER_SIZE3;
+       event->u.net.data = gen->buf + HEADER_SIZE3;
+       if (type == NP_endConn) return E_lostConn;
        return E_net;
 }
 
-ExtFunc void CheckNetConn(void)
-{
-}
+void SendPacket(short uid, NetPacketType type, int size, void *data)
+{ //send shit to server
+       netint4 header[3];
 
-ExtFunc void SendPacket(NetPacketType type, int size, void *data)
-{
-       netint2 header[2];
-
-       header[0] = hton2(type);
-       header[1] = hton2(size + HEADER_SIZE);
-       if (MyWrite(sock, header, HEADER_SIZE) != HEADER_SIZE)
-               die("write");
-       if (size > 0 && data && MyWrite(sock, data, size) != size)
+       header[0] = hton4(uid);
+       header[1] = hton4(type);
+       header[2] = hton4(size + HEADER_SIZE3);
+       if (MyWrite(netGen.fd, header, HEADER_SIZE3) != HEADER_SIZE3)
+               die("write (header)");
+       if (size > 0 && data && MyWrite(netGen.fd, data, size) != size)
                die("write");
 }
 
-ExtFunc void CloseNet(void)
-{
+void CloseNet(void)
+{ //kick some connection's ass!
        MyEvent event;
 
-       if (sock >= 0) {
-               if (!lostConn) {
-                       SendPacket(NP_endConn, 0, NULL);
-                       if (isServer) {
-                               while (!lostConn)
-                                       WaitMyEvent(&event, EM_net);
-                       }
-                       else {
-                               while (!gotEndConn)
-                                       WaitMyEvent(&event, EM_net);
-                               SendPacket(NP_byeBye, 0, NULL);
-                       }
-               }
-               close(sock);
-               sock = -1;
+       if (netGen.fd >= 0) {
+               SendPacket(0, NP_endConn, 0, NULL);
+               close(netGen.fd);
+               netGen.fd = -1;
        }
        if (netGen.next)
                RemoveEventGen(&netGen);
 }
 
-/*
- * vi: ts=4 ai
- * vim: noai si
- */