v0.9beta3
Fix some window related issues and implement our own version of poll (hopefully allows it to run on XP)
Adrian Smith
11 years ago
66 | 66 | } |
67 | 67 | |
68 | 68 | void sighandler(int signum) { |
69 | LOG_ERROR("signal"); | |
70 | 69 | slimproto_stop(); |
71 | 70 | } |
72 | 71 |
674 | 674 | |
675 | 675 | } else { |
676 | 676 | |
677 | LOG_INFO("connected"); | |
678 | ||
679 | var_cap[0] = '\0'; | |
680 | ||
681 | #if !WIN | |
682 | // check if this is a local player now we are connected & signal to server via 'loc' format | |
683 | // this requires LocalPlayer server plugin to enable direct file access | |
684 | // not supported on windows at present as the poll in stream.c does not work for file access | |
677 | 685 | struct sockaddr_in our_addr; |
678 | 686 | socklen_t len; |
679 | ||
680 | LOG_INFO("connected"); | |
681 | ||
682 | var_cap[0] = '\0'; | |
683 | ||
684 | // check if this is a local player now we are connected & signal to server via 'loc' format | |
685 | // this requires LocalPlayer server plugin to enable direct file access | |
686 | 687 | len = sizeof(our_addr); |
687 | 688 | getsockname(sock, (struct sockaddr *) &our_addr, &len); |
688 | ||
689 | ||
689 | 690 | if (our_addr.sin_addr.s_addr == serv_addr.sin_addr.s_addr) { |
690 | 691 | LOG_INFO("local player"); |
691 | 692 | strcat(var_cap, ",loc"); |
692 | 693 | } |
694 | #endif | |
693 | 695 | |
694 | 696 | // add on any capablity to be sent to the new server |
695 | 697 | if (new_server_cap) { |
17 | 17 | * |
18 | 18 | */ |
19 | 19 | |
20 | #define VERSION "v0.9beta2" | |
20 | #define VERSION "v0.9beta3" | |
21 | 21 | |
22 | 22 | // build detection |
23 | 23 | #if defined(linux) |
187 | 187 | #define in_addr_t u32_t |
188 | 188 | #define socklen_t int |
189 | 189 | |
190 | #define poll WSAPoll // FIXME? - limits support to Vista and later | |
191 | ||
192 | 190 | #define dlopen(x, y) LoadLibrary((LPCTSTR)x) |
193 | 191 | #define dlsym(x, y) (void *)GetProcAddress(x, y) |
194 | #define dlerror() GetLastError() ? "dlerror" : NULL | |
192 | //dlerror implemented in utils.c | |
195 | 193 | |
196 | 194 | #endif |
197 | 195 | |
272 | 270 | #if WIN |
273 | 271 | void winsock_init(void); |
274 | 272 | void winsock_close(void); |
273 | char *dlerror(void); | |
274 | int poll(struct pollfd *fds, unsigned long numfds, int timeout); | |
275 | 275 | #endif |
276 | 276 | |
277 | 277 | // buffer.c |
44 | 44 | while (len) { |
45 | 45 | n = send(fd, ptr, len, 0); |
46 | 46 | if (n <= 0) { |
47 | if (n < 0 && errno == EAGAIN && try < 10) { | |
47 | if (n < 0 && last_error() == EAGAIN && try < 10) { | |
48 | 48 | LOG_SDEBUG("retrying (%d) writing to socket", ++try); |
49 | 49 | usleep(1000); |
50 | 50 | continue; |
79 | 79 | struct pollfd pollinfo = { fd, 0, 0 }; |
80 | 80 | size_t space; |
81 | 81 | |
82 | if (fd < 0) { | |
83 | usleep(100000); | |
84 | continue; | |
85 | } | |
86 | ||
87 | 82 | LOCK; |
88 | 83 | space = min(_buf_space(streambuf), _buf_cont_write(streambuf)); |
89 | ||
90 | if (stream.state > STREAMING_WAIT && space) { | |
84 | UNLOCK; | |
85 | ||
86 | if (fd >= 0 && stream.state > STREAMING_WAIT && space) { | |
91 | 87 | pollinfo.events = POLLIN; |
92 | 88 | if (stream.state == SEND_HEADERS) { |
93 | 89 | pollinfo.events |= POLLOUT; |
94 | 90 | } |
91 | } else { | |
92 | usleep(100000); | |
93 | continue; | |
95 | 94 | } |
96 | ||
97 | UNLOCK; | |
98 | 95 | |
99 | 96 | if (poll(&pollinfo, 1, 100)) { |
100 | 97 | |
119 | 116 | |
120 | 117 | int n = recv(fd, &c, 1, 0); |
121 | 118 | if (n <= 0) { |
122 | if (n < 0 && errno == EAGAIN) { | |
119 | if (n < 0 && last_error() == EAGAIN) { | |
123 | 120 | UNLOCK; |
124 | 121 | continue; |
125 | 122 | } |
161 | 158 | u8_t c; |
162 | 159 | int n = recv(fd, &c, 1, 0); |
163 | 160 | if (n <= 0) { |
164 | if (n < 0 && errno == EAGAIN) { | |
161 | if (n < 0 && last_error() == EAGAIN) { | |
165 | 162 | UNLOCK; |
166 | 163 | continue; |
167 | 164 | } |
178 | 175 | if (stream.meta_left) { |
179 | 176 | int n = recv(fd, stream.header + stream.header_len, stream.meta_left, 0); |
180 | 177 | if (n <= 0) { |
181 | if (n < 0 && errno == EAGAIN) { | |
178 | if (n < 0 && last_error() == EAGAIN) { | |
182 | 179 | UNLOCK; |
183 | 180 | continue; |
184 | 181 | } |
217 | 214 | LOG_INFO("end of stream"); |
218 | 215 | _disconnect(DISCONNECT, DISCONNECT_OK); |
219 | 216 | } |
220 | if (n < 0 && errno != EAGAIN) { | |
217 | if (n < 0 && last_error() != EAGAIN) { | |
221 | 218 | LOG_WARN("error reading: %s", strerror(last_error())); |
222 | 219 | _disconnect(DISCONNECT, REMOTE_DISCONNECT); |
223 | 220 | } |
238 | 238 | void winsock_close(void) { |
239 | 239 | WSACleanup(); |
240 | 240 | } |
241 | #endif | |
242 | ||
241 | ||
242 | char *dlerror(void) { | |
243 | static char ret[32]; | |
244 | int last = GetLastError(); | |
245 | if (last) { | |
246 | sprintf(ret, "code: %i", last); | |
247 | SetLastError(0); | |
248 | return ret; | |
249 | } | |
250 | return NULL; | |
251 | } | |
252 | ||
253 | // this only implements numfds == 1 | |
254 | int poll(struct pollfd *fds, unsigned long numfds, int timeout) { | |
255 | fd_set r, w; | |
256 | struct timeval tv; | |
257 | int ret; | |
258 | ||
259 | FD_ZERO(&r); | |
260 | FD_ZERO(&w); | |
261 | ||
262 | if (fds[0].events & POLLIN) FD_SET(fds[0].fd, &r); | |
263 | if (fds[0].events & POLLOUT) FD_SET(fds[0].fd, &w); | |
264 | ||
265 | tv.tv_sec = timeout / 1000; | |
266 | tv.tv_usec = 1000 * (timeout % 1000); | |
267 | ||
268 | ret = select(fds[0].fd + 1, &r, &w, NULL, &tv); | |
269 | ||
270 | if (ret < 0) return ret; | |
271 | ||
272 | fds[0].revents = 0; | |
273 | if (FD_ISSET(fds[0].fd, &r)) fds[0].revents |= POLLIN; | |
274 | if (FD_ISSET(fds[0].fd, &w)) fds[0].revents |= POLLOUT; | |
275 | ||
276 | return ret; | |
277 | } | |
278 | ||
279 | #endif | |
280 |