2 * $Source: /cvs/cvsroot/d2x/main/ipclient.cpp,v $
5 * $Date: 2002-02-15 06:41:42 $
7 * ipclient.cpp - udp/ip client code
8 * added 2000/02/07 Matt Mueller
10 * $Log: not supported by cvs2svn $
11 * Revision 1.2 2002/02/14 09:27:09 bradleyb
14 * Revision 1.1 2002/02/06 09:22:42 bradleyb
15 * Adding d1x network code
30 void network_init(void);
31 int get_and_show_netgame_info(ubyte *server, ubyte *node, ubyte *net_address);
38 extern int Player_num;
39 extern int Network_send_objects;
43 int ip_connect_manual(char *textaddr) {
44 // ip_handshake_info handshake;
45 // ip_init_handshake_info(&handshake,0);
51 if (addr.dns(textaddr,UDP_BASEPORT)) {
52 nm_messagebox(TXT_ERROR,1,TXT_OK,"Could not resolve address");
56 con_printf(CON_DEBUG, "connecting to ");
58 con_printf(CON_DEBUG, "\n");
64 if (!(p=peer_list.find_by_addr(addr))){
65 p=peer_list.add_1(addr);
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);
76 mprintf((0,MSGHDR "ip_connect_manual: weird, someone sent us normal data\n"));
77 if (key_inkey()==KEY_ESC)
80 if (hsi->state&STATE_ERR) {
81 nm_messagebox(TXT_ERROR,1,TXT_OK,"handshake timeout");
87 return get_and_show_netgame_info(null_addr,p->id.id,NULL);
91 static int ipx_ip_OpenSocket(int oport) {
93 if ((i=FindArg("-ip_baseport"))){
94 baseport=UDP_BASEPORT+atoi(Args[i+1]);
97 myport=baseport+(oport - IPX_DEFAULT_SOCKET);
98 if (arch_ip_open_socket(myport)) return -1;
100 if (ipx_ip_GetMyAddress() < 0) FAIL("Error getting my address");
103 // port = dynamic_socket++;
105 msg("OpenSocket on D1X socket port %d (%d : %+d) : %+d",myport,oport,oport-IPX_DEFAULT_SOCKET,baseport-UDP_BASEPORT);
107 //sk->socket = UDP_BASEPORT+(oport - IPX_DEFAULT_SOCKET);
108 // sk->socket = port;
111 static void ipx_ip_CloseSocket(void) {
113 msg("CloseSocket on D1X socket port %d",myport);
115 arch_ip_close_socket();
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.
126 static int ipx_ip_SendPacket(IPXPacket_t *IPXHeader,
127 ubyte *data, int dataLen) {
128 // struct sockaddr_in toaddr;
133 if (dataLen<0 || dataLen>MAX_PACKETSIZE) {
135 msg("SendPacket enter, dataLen=%d out of range",dataLen);
139 chk(buf=(char*)alloca(2+dataLen));
140 memcpy(buf+0,D2Xid ,2);
141 memcpy(buf+2,data,dataLen);
144 con_printf(CON_DEBUG, MSGHDR "sendto((%d),Node=[4] %02X %02X,Socket=%02X %02X,s_port=%u,",
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");
153 //toaddr.sin_family=AF_INET;
154 if (memcmp(broadcast_addr,IPXHeader->Destination.Node,6)==0){
157 // ushort port=htons(myport);
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);
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);
173 //toaddr.sin_port=htons(((short)ntohs(*(unsigned short *)(IPXHeader->Destination.Node+4)))+UDP_BASEPORT);
174 // toaddr.sin_port=*(unsigned short *)(IPXHeader->Destination.Socket);
176 // i=sendto(mysock->fd,buf,2+dataLen,
177 // 0,(struct sockaddr *)&toaddr,sizeof(toaddr));
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.
187 static int ipx_ip_ReceivePacket(char *outbuf, int outbufsize,
188 struct ipx_recv_data *rd) {
194 if ((size=arch_ip_recvfrom(outbuf,outbufsize,rd))<0)
197 if (size<2) return -1;
199 memcpy(&fromaddr,rd->src_node,sizeof(ip_addr*));
201 if (memcmp(outbuf+0,D2Xid,2)) {
202 if (memcmp(outbuf+0,D2Xcfgid,4)) {
203 mprintf((0,MSGHDR"no valid header\n"));
208 memcpy(buf,&fromaddr.sin_addr,4);
209 *(unsigned short *)(buf+4)=fromaddr.sin_port;*/
211 // fromaddr.set(4,rd->src_node,*(unsigned short*)(rd->src_node+4));
212 ip_receive_cfg((ubyte*)outbuf+4,size-4,*fromaddr);
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) {
223 msg(" - pkt was dropped (dst=%d,my=%d)",rd->src_socket,s->socket);
227 // rd->src_socket = s->socket;
228 // rd->dst_socket = s->socket;
230 memmove(outbuf,outbuf+offs,size-(offs));
233 rd->src_socket = myport;
234 rd->dst_socket = myport;
238 con_printf(CON_DEBUG, MSGHDR "ReceivePacket: size=%d,from=",size);
239 // dumpraddr(rd->src_node);
241 con_printf(CON_DEBUG, "\n");
243 /* ip_peer *p=peer_list.find_by_addr(*fromaddr);
245 p->id.fillbuf(rd->src_node);
247 memset(rd->src_node,0,6);*/
248 if (ip_my_addrs.hasaddr(*fromaddr))
249 memcpy(rd->src_node,ipx_MyAddress+4,6);
251 memset(rd->src_node,0,6);
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();
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.
265 ip_peer *p=peer_list.find_byid(node);
266 if (!p || p->addr.goodaddr==NULL)
269 ip_handshake_relay *hsr;
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.
281 hsr=p->find_relay(np->id);
283 hsr=new ip_handshake_relay(np);
289 hsr=np->find_relay(p->id);
291 hsr=new ip_handshake_relay(p);
306 struct ipx_driver ipx_ip = {
307 // ipx_ip_GetMyAddress,
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