1 /*
2 * P2P Test
3 * kf701.ye, bob.suju
4 *
5 * Compile:
6 * Linux: gcc p2p.c -o p2p.out
7 * Windows: gcc p2p.c -o p2p.out -lws2_32
8 */
9
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
18 #include
19
20 #ifdef WIN32
21
22 #include
23 #include
24 #include
25 #include
26 #include
27 #include
28 #include
29
30 #else
31
32 #include
33 #include
34 #include
35 #include
36 #include
38 #include
39 #include
40
41 #define SOCKET int
42
43 #endif
44
45
46 #ifdef WIN32
47 void initWin32() {
48 WSADATA wsaData;
49 int err;
50
51 err = WSAStartup(MAKEWORD(2, 2), &wsaData );
52 if( err != 0 ) {
53 /* Tell the user that we could not find a usable */
54 /* WinSock DLL. */
55 printf("FATAL ERROR: unable to initialise Winsock 2.x.");
56 exit(-1);
57 }
58 }
59 #endif
60
61 SOCKET open_udp_socket(uint16_t local_port)
62 {
63 SOCKET sock_fd;
64 struct sockaddr_in local_address;
65 int sockopt = 1;
66
67 if((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
68 return(-1);
69 }
70
71
72 setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt));
73
74 memset(&local_address, 0, sizeof(local_address));
75 local_address.sin_family = AF_INET;
76 local_address.sin_port = htons(local_port);
77 local_address.sin_addr.s_addr = INADDR_ANY;
78 if(bind(sock_fd, (struct sockaddr*) &local_address, sizeof(local_address)) == -1) {
79 return(-1);
80 }
81
82 return(sock_fd);
83 }
84
85 char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) {
86 char *cp, *retStr;
87 uint32_t byte;
88 int n;
89
90 cp = &buf[buf_len];
91 *--cp = '\0';
92
93 n = 4;
94 do {
95 byte = addr & 0xff;
96 *--cp = byte % 10 + '0';
97 byte /= 10;
98 if (byte > 0) {
99 *--cp = byte % 10 + '0';
100 byte /= 10;
101 if (byte > 0)
102 *--cp = byte + '0';
103 }
104 *--cp = '.';
105 addr >>= 8;
106 } while (--n > 0);
107
108 /* Convert the string to lowercase */
109 retStr = (char*)(cp+1);
110
111 return(retStr);
112 }
113
114
115 void print_addr (struct sockaddr_in *addr)
116 {
117 char ip_buf[48];
118 printf ("%s:%d\n", intoa(ntohl(addr->sin_addr.s_addr), ip_buf, sizeof(ip_buf)), ntohs(addr->sin_port));
119 }
120
121 int Peer (char *serverip)
122 {
123 char buf[1024];
124
125 SOCKET sock = open_udp_socket (9000);
126 if (sock < 0)
127 {
128 printf ("open sock faild\n");
129 return 0;
130 }
131
132 struct sockaddr_in addr, sa;
133
134 addr.sin_family = AF_INET;
135 addr.sin_port = htons(8888);
136 addr.sin_addr.s_addr = inet_addr(serverip);
137
138 int rc, ret;
139 socklen_t len = sizeof( struct sockaddr_in );
140
141 while (1)
142 {
143 fd_set socket_mask;
144 struct timeval wait_time;
145
146 FD_ZERO(&socket_mask);
147 FD_SET(sock, &socket_mask);
148
149 wait_time.tv_sec = 1; wait_time.tv_usec = 0;
150
151 rc = select(sock+1, &socket_mask, NULL, NULL, &wait_time);
152
153 if (rc > 0 && FD_ISSET(sock, &socket_mask))
154 {
155 printf ("--------------------\n");
156 memset (buf, 0, sizeof(buf));
157
158 ret = recvfrom (sock, buf, sizeof(buf), 0, (struct sockaddr*)&sa, &len);
159
160 printf ("Recv From: ");
161 print_addr (&sa);
162 printf ("Recv buf: %s\n", buf);
163
164 if (sa.sin_addr.s_addr == inet_addr(serverip))
165 {
166 char *host = strtok(buf, ":");
167 char *port = strtok(NULL, ":");
168
169 if (host && port)
170 {
171 printf ("Re write addr to: %s:%s\n", host, port);
172 addr.sin_addr.s_addr = inet_addr(host);
173 addr.sin_port = htons(atoi(port));
174 }
175 }
176 else
177 {
178 printf ("Got From peer, P2P OK!\n");
179 }
180 }
181 else
182 {
183 char *b = "P2PTESTSTRING";
184 ret = sendto(sock, b, strlen(b), 0, (struct sockaddr*)&addr, len);
185 printf ("send buf len = %d to ",ret);
186 print_addr (&addr);
187 }
188 }
189 }
190
191 int Rendezvous()
192 {
193 struct sockaddr_in addr, peers_addr[2];
194 socklen_t len = sizeof( struct sockaddr_in );
195 int reach = 0, select_ret, ret;
196 uint8_t buf[1024];
197
198 SOCKET sockfd = open_udp_socket(8888);
199
200 while( 1 )
201 {
202 fd_set readset;
203 FD_ZERO(&readset);
204 FD_SET( sockfd , &readset );
205
206 select_ret = select(sockfd+1, &readset, NULL, NULL, NULL);
207 if (select_ret < 0)
208 {
209 printf("%s,%d: select err,%m\n", __FILE__, __LINE__);
210 continue;
211 }
212
213 if (FD_ISSET (sockfd, &readset))
214 {
215 printf ("--------------------\n");
216 memset (buf, 0, sizeof(buf));
217
218 ret = recvfrom(sockfd, (void*)buf, sizeof(buf) ,0, (struct sockaddr*)&addr, &len);
219 if (ret <= 0)
220 {
221 printf("%s: recvfrom err\n", __func__);
222 continue;
223 }
224
225 printf ("Recv From: ");
226 print_addr (&addr);
227 printf ("Recv buf: %s\n", buf);
228
229 if (reach != 0)
230 {
231 if (addr.sin_addr.s_addr == peers_addr[0].sin_addr.s_addr)
232 {
233 continue;
234 }
235 }
236
237
238 memcpy(&peers_addr[reach], &addr, len);
239 reach++;
240
241 if (reach == 2)
242 {
243 char public[64];
244
245 // -------------------------------------
246 sprintf(public, "%s:%d",
247 inet_ntoa(peers_addr[0].sin_addr), ntohs(peers_addr[0].sin_port));
248
249 ret = sendto(sockfd, public, strlen(public),
250 0, (struct sockaddr*)&peers_addr[1], sizeof(struct sockaddr_in));
251
252 printf("send to %s:%d msg: %s\n",
253 inet_ntoa(peers_addr[1].sin_addr), ntohs(peers_addr[1].sin_port), public);
254
255
256 // -------------------------------------
257 sprintf(public, "%s:%d",
258 inet_ntoa(peers_addr[1].sin_addr), ntohs(peers_addr[1].sin_port));
259
260 ret = sendto(sockfd, public, strlen(public),
261 0, (struct sockaddr*)&peers_addr[0], sizeof(struct sockaddr_in));
262
263 printf("send to %s:%d msg: %s\n",
264 inet_ntoa(peers_addr[0].sin_addr), ntohs(peers_addr[0].sin_port), public);
265
266 // -------------------------------------
267 printf ("--------- send again -------------\n");
268 // -------------------------------------
269 sprintf(public, "%s:%d",
270 inet_ntoa(peers_addr[1].sin_addr), ntohs(peers_addr[1].sin_port));
271
272 ret = sendto(sockfd, public, strlen(public),
273 0, (struct sockaddr*)&peers_addr[0], sizeof(struct sockaddr_in));
274
275 printf("send to %s:%d msg: %s\n",
276 inet_ntoa(peers_addr[0].sin_addr), ntohs(peers_addr[0].sin_port), public);
277
278 // -------------------------------------
279 sprintf(public, "%s:%d",
280 inet_ntoa(peers_addr[0].sin_addr), ntohs(peers_addr[0].sin_port));
281
282 ret = sendto(sockfd, public, strlen(public),
283 0, (struct sockaddr*)&peers_addr[1], sizeof(struct sockaddr_in));
284
285 printf("send to %s:%d msg: %s\n",
286 inet_ntoa(peers_addr[1].sin_addr), ntohs(peers_addr[1].sin_port), public);
287
288 reach = 0;
289 }
290 }
291 }
292
293 return 0;
294 }
295
296
297 int main (int argc, char **argv)
298 {
299 if (argc < 2)
300 {
301 printf ("Usage: p2p <0|1> [serverip]\n");
302 printf (" 1, run as server\n");
303 printf (" 0, run as peer\n");
304 printf ("./p2p 1\n");
305 printf ("./p2p 0 119.23.34.5\n");
306 return 0;
307 }
308
309 #ifdef WIN32
310 printf ("init windows socket\n");
311 initWin32();
312 #endif
313
314 if (atoi(argv[1]) == 1)
315 {
316 return Rendezvous ();
317 }
318 else
319 {
320 if (argc == 3)
321 return Peer (argv[2]);
322
323 printf ("argv error\n");
324 }
325
326 return 0;
327 }