]> icculus.org git repositories - btb/d2x.git/blob - main/ipclient.cpp
formatting, patch for better d1 texture conversion from Martin Schaffner <maschaffner...
[btb/d2x.git] / main / ipclient.cpp
1 /*
2  * $Source: /cvs/cvsroot/d2x/main/ipclient.cpp,v $
3  * $Revision: 1.3 $
4  * $Author: bradleyb $
5  * $Date: 2002-02-15 06:41:42 $
6  *
7  * ipclient.cpp - udp/ip client code
8  * added 2000/02/07 Matt Mueller
9  *
10  * $Log: not supported by cvs2svn $
11  * Revision 1.2  2002/02/14 09:27:09  bradleyb
12  * d1x->d2x
13  *
14  * Revision 1.1  2002/02/06 09:22:42  bradleyb
15  * Adding d1x network code
16  *
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 extern "C"{
25 #include "mono.h"
26 #include "key.h"
27 #include "text.h"
28 #include "newmenu.h"
29 #include "args.h"
30 void network_init(void);
31 int get_and_show_netgame_info(ubyte *server, ubyte *node, ubyte *net_address);
32 }
33
34 #include "ip_base.h"
35 #include "ipclient.h"
36
37
38 extern int Player_num;
39 extern int Network_send_objects;
40
41 extern int N_players;
42
43 int ip_connect_manual(char *textaddr) {
44 //  ip_handshake_info handshake;
45 //  ip_init_handshake_info(&handshake,0);
46     int r;
47     ubyte buf[1500];
48     ip_peer *p;
49         ip_addr addr;
50
51     if (addr.dns(textaddr,UDP_BASEPORT)) {
52                 nm_messagebox(TXT_ERROR,1,TXT_OK,"Could not resolve address");
53                 return -1;
54         }
55 #ifdef UDPDEBUG
56     con_printf(CON_DEBUG, "connecting to ");
57     addr.dump();
58     con_printf(CON_DEBUG, "\n");
59 #endif
60
61     network_init();
62     N_players = 0;
63
64     if (!(p=peer_list.find_by_addr(addr))){
65         p=peer_list.add_1(addr);
66     }
67     ip_handshake_info *hsi=p->find_handshake();
68         hsi->setstate(STATE_INEEDINFO);
69    // p->newhandshake(hsi);
70 //      p->handshakes.push_back(hsi);
71 //  set_hs_state(&hsr->reply,IPHELLO);
72 //  ip_send_handshake(hsr,&hsr->reply);
73     while(hsi->state&STATE_VALID_STATES){
74         r=ipx_get_packet_data(buf);
75         if (r>0)
76             mprintf((0,MSGHDR "ip_connect_manual: weird, someone sent us normal data\n"));
77         if (key_inkey()==KEY_ESC)
78             return 0;
79     }
80     if (hsi->state&STATE_ERR) {
81                 nm_messagebox(TXT_ERROR,1,TXT_OK,"handshake timeout");
82                 return -1;
83         }
84
85 //  join the Netgame.
86
87     return get_and_show_netgame_info(null_addr,p->id.id,NULL);
88 }
89
90
91 static int ipx_ip_OpenSocket(int oport) {
92         int i;
93         if ((i=FindArg("-ip_baseport"))){
94                 baseport=UDP_BASEPORT+atoi(Args[i+1]);
95         }
96
97         myport=baseport+(oport - IPX_DEFAULT_SOCKET);
98         if (arch_ip_open_socket(myport)) return -1;
99
100         if (ipx_ip_GetMyAddress() < 0) FAIL("Error getting my address");
101
102         //      if (!port)
103         //              port = dynamic_socket++;
104 #ifdef UDPDEBUG
105         msg("OpenSocket on D1X socket port %d (%d : %+d) : %+d",myport,oport,oport-IPX_DEFAULT_SOCKET,baseport-UDP_BASEPORT);
106 #endif
107         //sk->socket = UDP_BASEPORT+(oport - IPX_DEFAULT_SOCKET);
108 //      sk->socket = port;
109         return 0;
110 }
111 static void ipx_ip_CloseSocket(void) {
112 #ifdef UDPDEBUG
113         msg("CloseSocket on D1X socket port %d",myport);
114 #endif
115         arch_ip_close_socket();
116         peer_list.clear();
117 }
118
119
120
121 /* Here we'll send the packet to our host. If it is unicast packet, send
122  * it to IP address/port as retrieved from IPX address. Otherwise (broadcast)
123  * we'll repeat the same data to each host in our broadcasting list.
124  */
125
126 static int ipx_ip_SendPacket(IPXPacket_t *IPXHeader,
127                 ubyte *data, int dataLen) {
128 //      struct sockaddr_in toaddr;
129         int i=dataLen;
130         //int bcast;
131         char *buf;
132
133         if (dataLen<0 || dataLen>MAX_PACKETSIZE) {
134 #ifdef UDPDEBUG
135                 msg("SendPacket enter, dataLen=%d out of range",dataLen);
136 #endif
137                 return -1;
138         }
139         chk(buf=(char*)alloca(2+dataLen));
140         memcpy(buf+0,D2Xid ,2);
141         memcpy(buf+2,data,dataLen);
142
143 #ifdef UDPDEBUG
144         con_printf(CON_DEBUG, MSGHDR "sendto((%d),Node=[4] %02X %02X,Socket=%02X %02X,s_port=%u,",
145                         dataLen,
146                         IPXHeader->Destination.Node [4],IPXHeader->Destination.Node  [5],
147                         IPXHeader->Destination.Socket[0],IPXHeader->Destination.Socket[1],
148                         ntohs(*(unsigned short *)(IPXHeader->Destination.Socket)));
149         dumprid(IPXHeader->Destination.Node);
150         con_printf(CON_DEBUG, ").\n");
151 #endif
152
153         //toaddr.sin_family=AF_INET;
154         if (memcmp(broadcast_addr,IPXHeader->Destination.Node,6)==0){
155 //              ubyte brbuf[6];
156                 ip_addr brbuf;
157 //              ushort port=htons(myport);
158 //              //int j;
159 //              memcpy(brbuf+0,IPXHeader->Destination.Node+0,4);
160 //              //memcpy(brbuf+4,IPXHeader->Destination.Socket,2);
161 //              memcpy(brbuf+4,&port,2);
162                 brbuf.set(4,IPXHeader->Destination.Node,htons(myport));
163                 i=ip_sendtoca(brbuf,buf,2+dataLen);
164 //              memcpy(&toaddr.sin_addr,IPXHeader->Destination.Node+0,4);
165 //              toaddr.sin_port=*(unsigned short *)(IPXHeader->Destination.Socket);
166                 ip_sendtoall(buf,2+dataLen);
167         }else {
168                 i=ip_sendtoid(IPXHeader->Destination.Node,buf,2+dataLen);
169 //              memcpy(&toaddr.sin_addr,hsr->addr[hsr->goodaddr],4);
170 //              toaddr.sin_port=*(unsigned short *)(hsr->addr[hsr->goodaddr]+4);
171 ////            toaddr.sin_port=*(unsigned short *)(IPXHeader->Destination.Node+4);
172         }
173                 //toaddr.sin_port=htons(((short)ntohs(*(unsigned short *)(IPXHeader->Destination.Node+4)))+UDP_BASEPORT);
174 //      toaddr.sin_port=*(unsigned short *)(IPXHeader->Destination.Socket);
175
176 //      i=sendto(mysock->fd,buf,2+dataLen,
177 //                      0,(struct sockaddr *)&toaddr,sizeof(toaddr));
178         return(i<1?-1:i-1);
179 }
180
181 /* Here we will receive new packet to the given buffer. Both formats of packets
182  * are supported, we fallback to old format when first obsolete packet is seen.
183  * If the (valid) packet is received from unknown host, we will add it to our
184  * broadcasting list. FIXME: For now such autoconfigured hosts are NEVER removed.
185  */
186
187 static int ipx_ip_ReceivePacket(char *outbuf, int outbufsize, 
188  struct ipx_recv_data *rd) {
189         int size;
190         size_t offs;
191         ip_addr *fromaddr;
192         //int i;
193
194         if ((size=arch_ip_recvfrom(outbuf,outbufsize,rd))<0)
195                 return -1;
196
197         if (size<2) return -1;
198
199         memcpy(&fromaddr,rd->src_node,sizeof(ip_addr*));
200
201         if (memcmp(outbuf+0,D2Xid,2)) {
202                 if (memcmp(outbuf+0,D2Xcfgid,4)) {
203                         mprintf((0,MSGHDR"no valid header\n"));
204                         return -1;
205                 }
206                 {
207 /*                      ubyte buf[6];
208                         memcpy(buf,&fromaddr.sin_addr,4);
209                         *(unsigned short *)(buf+4)=fromaddr.sin_port;*/
210                         //do stuff.
211 //                      fromaddr.set(4,rd->src_node,*(unsigned short*)(rd->src_node+4));
212                         ip_receive_cfg((ubyte*)outbuf+4,size-4,*fromaddr);
213                 }
214                 return 0;
215         }
216         else offs=2;
217
218         /* Lace: (dst_socket & src_socket) should be network-byte-order by comment in include/ipx_drv.h */
219         /*       This behaviour presented here is broken. It is not used anywhere, so why bother? */
220 /*      rd->src_socket = ntohs(*(unsigned short *)(outbuf+offs));
221         if (rd->src_socket != s->socket) {
222 #ifdef UDPDEBUG
223                 msg(" - pkt was dropped (dst=%d,my=%d)",rd->src_socket,s->socket);
224 #endif
225                 return -1;
226                 }*/
227 //      rd->src_socket = s->socket;
228 //      rd->dst_socket = s->socket;
229
230         memmove(outbuf,outbuf+offs,size-(offs));
231         size-=offs;
232
233         rd->src_socket = myport;
234     rd->dst_socket = myport;
235
236         rd->pkt_type = 0;
237 #ifdef UDPDEBUG
238         con_printf(CON_DEBUG, MSGHDR "ReceivePacket: size=%d,from=",size);
239 //      dumpraddr(rd->src_node);
240         fromaddr->dump();
241         con_printf(CON_DEBUG, "\n");
242 #endif
243 /*      ip_peer *p=peer_list.find_by_addr(*fromaddr);
244         if(p)
245                 p->id.fillbuf(rd->src_node);
246         else
247                 memset(rd->src_node,0,6);*/
248         if (ip_my_addrs.hasaddr(*fromaddr))
249                 memcpy(rd->src_node,ipx_MyAddress+4,6);
250         else
251                 memset(rd->src_node,0,6);
252
253         return size;
254 }
255
256 static int ipx_ip_general_PacketReady(void) {
257         //ip_handshake_frame();//handle handshake resending
258         peer_list.handshake_frame();
259         return arch_ip_PacketReady();
260 }
261
262 static int ipx_ip_CheckReadyToJoin(ubyte *server, ubyte *node){
263         if (Network_send_objects) return 0;//if we are currently letting someone else join, we don't know if this person can join ok.
264
265         ip_peer *p=peer_list.find_byid(node);
266         if (!p || p->addr.goodaddr==NULL)
267                 return 0;
268         ip_peer *np;
269         ip_handshake_relay *hsr;
270         int j;
271         int ok,nope=0;
272
273         for (j=0;j<get_MAX_PLAYERS();j++){
274                 if (get_Netgame_player_connected(j) && j!=Player_num){
275                         np=peer_list.find_byid(get_Netgame_player_node(j));
276                         if (!np)continue;//huh??
277                         if (np->id==node)continue;//don't tell them to talk to themselves.
278
279                         ok=0;
280
281                         hsr=p->find_relay(np->id);
282                         if (!hsr){
283                                 hsr=new ip_handshake_relay(np);
284                                 p->add_hs(hsr);
285                         }
286                         if (hsr->state==0)
287                                 ok++;
288
289                         hsr=np->find_relay(p->id);
290                         if (!hsr){
291                                 hsr=new ip_handshake_relay(p);
292                                 np->add_hs(hsr);
293                         }
294                         if (hsr->state==0)
295                                 ok++;
296                         if (ok!=2)
297                                 nope++;
298                 }
299         }
300         if (nope)
301                 return 0;
302
303         return 1;
304 }
305
306 struct ipx_driver ipx_ip = {
307 //      ipx_ip_GetMyAddress,
308         ipx_ip_OpenSocket,
309         ipx_ip_CloseSocket,
310         ipx_ip_SendPacket,
311         ipx_ip_ReceivePacket,
312         ipx_ip_general_PacketReady,
313         ipx_ip_CheckReadyToJoin,
314         0, //save 4 bytes.  udp/ip is completely inaccessable by the other methods, so we don't need to worry about compatibility.
315         NULL, //use the easier ones
316         NULL, //use the easier ones
317         NULL  //use the easier ones
318 };