2 * $Source: /cvs/cvsroot/d2x/main/ipclient.cpp,v $
5 * $Date: 2002-02-06 09:22:42 $
7 * ipclient.cpp - udp/ip client code
8 * added 2000/02/07 Matt Mueller
10 * $Log: not supported by cvs2svn $
24 void network_init(void);
25 int get_and_show_netgame_info(ubyte *server, ubyte *node, ubyte *net_address);
32 extern int Player_num;
33 extern int Network_send_objects;
37 int ip_connect_manual(char *textaddr) {
38 // ip_handshake_info handshake;
39 // ip_init_handshake_info(&handshake,0);
45 if (addr.dns(textaddr,UDP_BASEPORT)) {
46 nm_messagebox(TXT_ERROR,1,TXT_OK,"Could not resolve address");
50 printf("connecting to ");
58 if (!(p=peer_list.find_by_addr(addr))){
59 p=peer_list.add_1(addr);
61 ip_handshake_info *hsi=p->find_handshake();
62 hsi->setstate(STATE_INEEDINFO);
63 // p->newhandshake(hsi);
64 // p->handshakes.push_back(hsi);
65 // set_hs_state(&hsr->reply,IPHELLO);
66 // ip_send_handshake(hsr,&hsr->reply);
67 while(hsi->state&STATE_VALID_STATES){
68 r=ipx_get_packet_data(buf);
70 mprintf((0,MSGHDR "ip_connect_manual: weird, someone sent us normal data\n"));
71 if (key_inkey()==KEY_ESC)
74 if (hsi->state&STATE_ERR) {
75 nm_messagebox(TXT_ERROR,1,TXT_OK,"handshake timeout");
81 return get_and_show_netgame_info(null_addr,p->id.id,NULL);
85 static int ipx_ip_OpenSocket(int oport) {
87 if ((i=FindArg("-ip_baseport"))){
88 baseport=UDP_BASEPORT+atoi(Args[i+1]);
91 myport=baseport+(oport - IPX_DEFAULT_SOCKET);
92 if (arch_ip_open_socket(myport)) return -1;
94 if (ipx_ip_GetMyAddress() < 0) FAIL("Error getting my address");
97 // port = dynamic_socket++;
99 msg("OpenSocket on D1X socket port %d (%d : %+d) : %+d",myport,oport,oport-IPX_DEFAULT_SOCKET,baseport-UDP_BASEPORT);
101 //sk->socket = UDP_BASEPORT+(oport - IPX_DEFAULT_SOCKET);
102 // sk->socket = port;
105 static void ipx_ip_CloseSocket(void) {
107 msg("CloseSocket on D1X socket port %d",myport);
109 arch_ip_close_socket();
115 /* Here we'll send the packet to our host. If it is unicast packet, send
116 * it to IP address/port as retrieved from IPX address. Otherwise (broadcast)
117 * we'll repeat the same data to each host in our broadcasting list.
120 static int ipx_ip_SendPacket(IPXPacket_t *IPXHeader,
121 ubyte *data, int dataLen) {
122 // struct sockaddr_in toaddr;
127 if (dataLen<0 || dataLen>MAX_PACKETSIZE) {
129 msg("SendPacket enter, dataLen=%d out of range",dataLen);
133 chk(buf=(char*)alloca(2+dataLen));
134 memcpy(buf+0,D1Xid ,2);
135 memcpy(buf+2,data,dataLen);
138 printf(MSGHDR "sendto((%d),Node=[4] %02X %02X,Socket=%02X %02X,s_port=%u,",
140 IPXHeader->Destination.Node [4],IPXHeader->Destination.Node [5],
141 IPXHeader->Destination.Socket[0],IPXHeader->Destination.Socket[1],
142 ntohs(*(unsigned short *)(IPXHeader->Destination.Socket)));
143 dumprid(IPXHeader->Destination.Node);
147 //toaddr.sin_family=AF_INET;
148 if (memcmp(broadcast_addr,IPXHeader->Destination.Node,6)==0){
151 // ushort port=htons(myport);
153 // memcpy(brbuf+0,IPXHeader->Destination.Node+0,4);
154 // //memcpy(brbuf+4,IPXHeader->Destination.Socket,2);
155 // memcpy(brbuf+4,&port,2);
156 brbuf.set(4,IPXHeader->Destination.Node,htons(myport));
157 i=ip_sendtoca(brbuf,buf,2+dataLen);
158 // memcpy(&toaddr.sin_addr,IPXHeader->Destination.Node+0,4);
159 // toaddr.sin_port=*(unsigned short *)(IPXHeader->Destination.Socket);
160 ip_sendtoall(buf,2+dataLen);
162 i=ip_sendtoid(IPXHeader->Destination.Node,buf,2+dataLen);
163 // memcpy(&toaddr.sin_addr,hsr->addr[hsr->goodaddr],4);
164 // toaddr.sin_port=*(unsigned short *)(hsr->addr[hsr->goodaddr]+4);
165 //// toaddr.sin_port=*(unsigned short *)(IPXHeader->Destination.Node+4);
167 //toaddr.sin_port=htons(((short)ntohs(*(unsigned short *)(IPXHeader->Destination.Node+4)))+UDP_BASEPORT);
168 // toaddr.sin_port=*(unsigned short *)(IPXHeader->Destination.Socket);
170 // i=sendto(mysock->fd,buf,2+dataLen,
171 // 0,(struct sockaddr *)&toaddr,sizeof(toaddr));
175 /* Here we will receive new packet to the given buffer. Both formats of packets
176 * are supported, we fallback to old format when first obsolete packet is seen.
177 * If the (valid) packet is received from unknown host, we will add it to our
178 * broadcasting list. FIXME: For now such autoconfigured hosts are NEVER removed.
181 static int ipx_ip_ReceivePacket(char *outbuf, int outbufsize,
182 struct ipx_recv_data *rd) {
188 if ((size=arch_ip_recvfrom(outbuf,outbufsize,rd))<0)
191 if (size<2) return -1;
193 memcpy(&fromaddr,rd->src_node,sizeof(ip_addr*));
195 if (memcmp(outbuf+0,D1Xid,2)) {
196 if (memcmp(outbuf+0,D1Xcfgid,4)) {
197 mprintf((0,MSGHDR"no valid header\n"));
202 memcpy(buf,&fromaddr.sin_addr,4);
203 *(unsigned short *)(buf+4)=fromaddr.sin_port;*/
205 // fromaddr.set(4,rd->src_node,*(unsigned short*)(rd->src_node+4));
206 ip_receive_cfg((ubyte*)outbuf+4,size-4,*fromaddr);
212 /* Lace: (dst_socket & src_socket) should be network-byte-order by comment in include/ipx_drv.h */
213 /* This behaviour presented here is broken. It is not used anywhere, so why bother? */
214 /* rd->src_socket = ntohs(*(unsigned short *)(outbuf+offs));
215 if (rd->src_socket != s->socket) {
217 msg(" - pkt was dropped (dst=%d,my=%d)",rd->src_socket,s->socket);
221 // rd->src_socket = s->socket;
222 // rd->dst_socket = s->socket;
224 memmove(outbuf,outbuf+offs,size-(offs));
227 rd->src_socket = myport;
228 rd->dst_socket = myport;
232 printf(MSGHDR "ReceivePacket: size=%d,from=",size);
233 // dumpraddr(rd->src_node);
237 /* ip_peer *p=peer_list.find_by_addr(*fromaddr);
239 p->id.fillbuf(rd->src_node);
241 memset(rd->src_node,0,6);*/
242 if (ip_my_addrs.hasaddr(*fromaddr))
243 memcpy(rd->src_node,ipx_MyAddress+4,6);
245 memset(rd->src_node,0,6);
250 static int ipx_ip_general_PacketReady(void) {
251 //ip_handshake_frame();//handle handshake resending
252 peer_list.handshake_frame();
253 return arch_ip_PacketReady();
256 static int ipx_ip_CheckReadyToJoin(ubyte *server, ubyte *node){
257 if (Network_send_objects) return 0;//if we are currently letting someone else join, we don't know if this person can join ok.
259 ip_peer *p=peer_list.find_byid(node);
260 if (!p || p->addr.goodaddr==NULL)
263 ip_handshake_relay *hsr;
267 for (j=0;j<get_MAX_PLAYERS();j++){
268 if (get_Netgame_player_connected(j) && j!=Player_num){
269 np=peer_list.find_byid(get_Netgame_player_node(j));
270 if (!np)continue;//huh??
271 if (np->id==node)continue;//don't tell them to talk to themselves.
275 hsr=p->find_relay(np->id);
277 hsr=new ip_handshake_relay(np);
283 hsr=np->find_relay(p->id);
285 hsr=new ip_handshake_relay(p);
300 struct ipx_driver ipx_ip = {
301 // ipx_ip_GetMyAddress,
305 ipx_ip_ReceivePacket,
306 ipx_ip_general_PacketReady,
307 ipx_ip_CheckReadyToJoin,
308 0, //save 4 bytes. udp/ip is completely inaccessable by the other methods, so we don't need to worry about compatibility.
309 NULL, //use the easier ones
310 NULL, //use the easier ones
311 NULL //use the easier ones