d76a7574ec5c7cd871e944794957073bebdda923
[pcsx_rearmed.git] / plugins / dfnet / dfnet.c
1 //
2 // DF Netplay Plugin
3 //
4 // Based on netSock 0.2 by linuzappz.
5 // The Plugin is free source code.
6 //
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 extern int errno;
16
17 #include "dfnet.h"
18
19 const unsigned char version  = 2;    // NET library v2
20 const unsigned char revision = 0;
21 const unsigned char build    = 3;    // increase that with each version
22
23 static char *libraryName      = N_("Socket Driver");
24
25 unsigned long CALLBACK PSEgetLibType() {
26         return PSE_LT_NET;
27 }
28
29 char* CALLBACK PSEgetLibName() {
30         return _(libraryName);
31 }
32
33 unsigned long CALLBACK PSEgetLibVersion() {
34         return version << 16 | revision << 8 | build;
35 }
36
37 long CALLBACK NETinit() {
38         return sockInit();
39 }
40
41 int SEND(const void *buf, int Size, int Mode) {
42         int bytes;
43         int count = 0;
44         const char *pData = (const char *)buf;
45
46         if (Mode & PSE_NET_NONBLOCKING) { // NONBLOCKING
47                 int ret;
48
49                 FD_ZERO(&wset);
50                 FD_SET(sock, &wset);
51
52                 ret = select(sock + 1, NULL, &wset, NULL, &tm);
53                 if (ret == -1) return -1;
54
55                 if (FD_ISSET(sock, &wset)) {
56                         return send(sock, pData, Size, 0);
57                 } else {
58                         return 0;
59                 }
60         } else { // BLOCKING
61                 while (Size > 0) {
62                         bytes = send(sock, pData, Size, 0);
63                         if (bytes < 0) return -1;
64                         pData += bytes; Size -= bytes;
65                         count += bytes;
66                 }
67         }
68
69         return count;
70 }
71
72 int RECV(void *buf, int Size, int Mode) {
73         int bytes;
74         int count = 0;
75         char *pData = (char *)buf;
76
77         if (Mode & PSE_NET_NONBLOCKING) { // NONBLOCKING
78                 int ret;
79
80                 FD_ZERO(&rset);
81                 FD_SET(sock, &rset);
82
83                 ret = select(sock, &rset, NULL, NULL, &tm);
84
85                 if (FD_ISSET(sock, &rset)) {
86                         return recv(sock, pData, Size, 0);
87                 } else {
88                         return 0;
89                 }
90         } else { // BLOCKING
91                 while (Size > 0) {
92                         bytes = recv(sock, pData, Size, 0);
93                         if (bytes == -1) return -1;
94                         pData+= bytes; Size-= bytes;
95                         count+= bytes;
96                 }
97         }
98
99         return count;
100 }
101
102 long CALLBACK NETopen(unsigned long *gpuDisp) {
103         int ret = sockOpen();
104
105         struct sockaddr_in address;
106
107         if (ret == -1) return -1;
108
109         if (conf.PlayerNum == 1) {
110                 int listen_sock, reuse_addr = 1;
111                 int ret;
112
113                 memset((char *)&address, 0, sizeof (address));
114
115                 address.sin_family = AF_INET;
116                 address.sin_port = htons(conf.PortNum);
117                 address.sin_addr.s_addr = INADDR_ANY;
118
119                 listen_sock = socket(AF_INET, SOCK_STREAM, 0);
120                 if (listen_sock == -1)
121                         return -1;
122
123                 setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_addr, sizeof(reuse_addr));
124
125                 if (bind(listen_sock,(struct sockaddr *) &address, sizeof(address)) == -1)
126                         return -1;
127
128                 if (listen(listen_sock, 1) != 0) 
129                         return -1; 
130
131                 sock = -1;
132
133                 WaitCancel = 0;
134                 sockCreateWaitDlg();
135
136                 while (sock < 0) {
137                         FD_ZERO(&rset);
138                         FD_SET(listen_sock, &rset);
139
140                         ret = select(listen_sock + 1, &rset, NULL, NULL, &tm);
141                         if (FD_ISSET(listen_sock, &rset)) {
142                                 sock = accept(listen_sock, NULL, NULL);
143                         }
144
145                         if (WaitCancel) break;
146                         sockDlgUpdate();
147                 }
148                 close(listen_sock);
149
150                 sockDestroyWaitDlg();
151                 if (WaitCancel == 1) return -1;
152         } else {
153                 memset((char *)&address, 0, sizeof(address));
154                 address.sin_family = AF_INET;
155                 address.sin_port = htons(conf.PortNum);
156                 address.sin_addr.s_addr = inet_addr(conf.ipAddress);
157
158                 sock = socket(AF_INET, SOCK_STREAM, 0);
159
160                 if (connect(sock, (struct sockaddr *)&address, sizeof(address))!=0) {
161                         SysMessage(_("error connecting to %s: %s\n"), conf.ipAddress, strerror(errno));
162                         return -1;
163                 }
164         }
165
166         PadInit = 0;
167         PadCount = 0;
168         PadSize[0] = -1;
169         PadSize[1] = -1;
170         PadRecvSize = -1;
171         PadSendSize = -1;
172         Ping = sockPing();
173         Ping = (sockPing() + Ping) / 2;
174         Ping = (sockPing() + Ping) / 2;
175
176         if (conf.PlayerNum == 1) {
177                 PadCountMax = (int)(((double)Ping / 1000.0) * 60.0);
178                 if (PadCountMax <= 0) PadCountMax = 1;
179                 SEND(&PadCountMax, 4, PSE_NET_BLOCKING);
180         } else {
181                 RECV(&PadCountMax, 4, PSE_NET_BLOCKING);
182         }
183
184         PadSendData = (char *)malloc(PadCountMax * 128);
185         if (PadSendData == NULL) {
186                 SysMessage(_("Error allocating memory!\n")); return -1;
187         }
188         memset(PadSendData, 0xff, PadCountMax);
189
190         return ret;
191 }
192
193 long CALLBACK NETclose() {
194         close(sock);
195
196         return 0;
197 }
198
199 long CALLBACK NETshutdown() {
200         return sockShutdown();
201 }
202
203 void CALLBACK NETpause() {
204 /*      unsigned char Code = 0x80;
205
206         SEND(&Code, 1, PSE_NET_BLOCKING);*/
207 }
208
209 void CALLBACK NETresume() {
210 /*      unsigned char Code = 0x80;
211
212         SEND(&Code, 1, PSE_NET_BLOCKING);*/
213 }
214
215 long CALLBACK NETsendData(void *pData, int Size, int Mode) {
216         return SEND(pData, Size, Mode);
217 }
218
219 long CALLBACK NETrecvData(void *pData, int Size, int Mode) {
220         return RECV(pData, Size, Mode);
221 }
222
223 long CALLBACK NETsendPadData(void *pData, int Size) {
224         if (PadSendSize == -1) {
225                 PadSendSize = Size;
226
227                 if (SEND(&PadSendSize, 1, PSE_NET_BLOCKING) == -1)
228                         return -1;
229
230                 if (RECV(&PadRecvSize, 1, PSE_NET_BLOCKING) == -1)
231                         return -1;
232         }
233
234         memcpy(&PadSendData[PadCount], pData, Size);
235         if (SEND(pData, PadSendSize, PSE_NET_BLOCKING) == -1)
236                 return -1;
237
238         return 0;
239 }
240
241 long CALLBACK NETrecvPadData(void *pData, int Pad) {
242         if (PadInit == 0) {
243                 if (conf.PlayerNum == Pad) {
244                         memset(pData, 0xff, PadSendSize);
245                 } else {
246                         memset(pData, 0xff, PadRecvSize);
247                 }
248         } else {
249                 if (conf.PlayerNum == Pad) {
250                         memcpy(pData, &PadSendData[PadCount == 0 ? PadCountMax-1 : PadCount-1], PadSendSize);
251                 } else {
252                         if (RECV(pData, PadRecvSize, PSE_NET_BLOCKING) == -1)
253                                 return -1;
254                 }
255         }
256
257         if (Pad == 2) {
258                 PadCount++;
259                 if (PadCount == PadCountMax) {
260                         PadCount = 0;
261                         PadInit = 1;
262                 }
263         }
264
265         return 0;
266 }
267
268 long CALLBACK NETqueryPlayer() {
269         return conf.PlayerNum;
270 }
271
272 long CALLBACK NETtest() {
273         return 0;
274 }