Commit | Line | Data |
---|---|---|
ef79bbde P |
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 | } |