]>
jfr.im git - solanum.git/blob - libratbox/src/win32.c
2 * ircd-ratbox: A slightly useful ircd.
3 * win32.c: select() compatible network routines.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2001 Adrian Chadd <adrian@creative.net.au>
8 * Copyright (C) 2005-2006 Aaron Sethman <androsyn@ratbox.org>
9 * Copyright (C) 2002-2006 ircd-ratbox development team
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
26 * $Id: win32.c 26092 2008-09-19 15:13:52Z androsyn $
29 #include <libratbox_config.h>
30 #include <ratbox_lib.h>
31 #include <commio-int.h>
37 #define WM_SOCKET WM_USER
39 * having gettimeofday is nice...
44 unsigned __int64 ft_i64
;
49 #define Const64(x) x##LL
51 #define Const64(x) x##i64
53 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
54 #define EPOCH_BIAS Const64(116444736000000000)
59 return GetCurrentProcessId();
64 rb_gettimeofday(struct timeval
*tp
, void *not_used
)
68 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
69 GetSystemTimeAsFileTime(&ft
.ft_val
);
71 /* seconds since epoch */
72 tp
->tv_sec
= (long)((ft
.ft_i64
- EPOCH_BIAS
) / Const64(10000000));
74 /* microseconds remaining */
75 tp
->tv_usec
= (long)((ft
.ft_i64
/ Const64(10)) % Const64(1000000));
82 rb_spawn_process(const char *path
, const char **argv
)
84 PROCESS_INFORMATION pi
;
87 memset(&pi
, 0, sizeof(pi
));
88 memset(&si
, 0, sizeof(si
));
89 rb_strlcpy(cmd
, path
, sizeof(cmd
));
90 if(CreateProcess(cmd
, cmd
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
) == FALSE
)
93 return (pi
.dwProcessId
);
97 rb_waitpid(int pid
, int *status
, int flags
)
99 DWORD timeout
= (flags
& WNOHANG
) ? 0 : INFINITE
;
103 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, pid
);
106 waitcode
= WaitForSingleObject(hProcess
, timeout
);
107 if(waitcode
== WAIT_TIMEOUT
)
109 CloseHandle(hProcess
);
112 else if(waitcode
== WAIT_OBJECT_0
)
114 if(GetExitCodeProcess(hProcess
, &waitcode
))
116 *status
= (int)((waitcode
& 0xff) << 8);
117 CloseHandle(hProcess
);
121 CloseHandle(hProcess
);
130 rb_setenv(const char *name
, const char *value
, int overwrite
)
136 if((buf
= getenv(name
)) != NULL
)
144 if(name
== NULL
|| value
== NULL
)
146 len
= strlen(name
) + strlen(value
) + 5;
147 buf
= rb_malloc(len
);
148 rb_snprintf(buf
, len
, "%s=%s", name
, value
);
155 rb_kill(int pid
, int sig
)
159 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, pid
);
170 if(TerminateProcess(hProcess
, sig
))
174 CloseHandle(hProcess
);
187 uint8_t protocol count
188 WSAPROTOCOL_INFO * count
195 make_wsaprotocol_info(pid_t process
, rb_fde_t
*F
, WSAPROTOCOL_INFO
* inf
)
197 WSAPROTOCOL_INFO info
;
198 if(!WSADuplicateSocket((SOCKET
) rb_get_fd(F
), process
, &info
))
200 memcpy(inf
, &info
, sizeof(WSAPROTOCOL_INFO
));
207 make_fde_from_wsaprotocol_info(void *data
)
209 WSAPROTOCOL_INFO
*info
= data
;
211 t
= WSASocket(FROM_PROTOCOL_INFO
, FROM_PROTOCOL_INFO
, FROM_PROTOCOL_INFO
, info
, 0, 0);
212 if(t
== INVALID_SOCKET
)
217 return rb_open(t
, RB_FD_SOCKET
, "remote_socket");
220 static uint8_t fd_buf
[16384];
221 #define MAGIC_CONTROL 0xFF0ACAFE
224 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)
227 sizeof(uint32_t) + sizeof(uint8_t) + (sizeof(WSAPROTOCOL_INFO
) * (size_t)count
) +
228 sizeof(size_t) + datasize
;
230 uint32_t magic
= MAGIC_CONTROL
;
237 if(bufsize
> sizeof(fd_buf
))
242 memset(fd_buf
, 0, sizeof(fd_buf
));
245 memcpy(ptr
, &magic
, sizeof(magic
));
246 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(magic
));
247 *((uint8_t *)ptr
) = count
;
248 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(uint8_t));
250 for(i
= 0; i
< count
; i
++)
252 make_wsaprotocol_info(pid
, F
[i
], (WSAPROTOCOL_INFO
*) ptr
);
253 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(WSAPROTOCOL_INFO
));
255 memcpy(ptr
, &datasize
, sizeof(size_t));
256 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(size_t));
257 memcpy(ptr
, data
, datasize
);
258 return rb_write(xF
, fd_buf
, bufsize
);
264 #define MYMIN(a, b) ((a) < (b) ? (a) : (b))
267 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
269 size_t minsize
= sizeof(uint32_t) + sizeof(uint8_t) + sizeof(size_t);
277 memset(fd_buf
, 0, sizeof(fd_buf
)); /* some paranoia here... */
278 ret
= rb_read(F
, fd_buf
, sizeof(fd_buf
));
283 if(ret
< (ssize_t
) minsize
)
289 memcpy(&magic
, ptr
, sizeof(uint32_t));
290 if(magic
!= MAGIC_CONTROL
)
295 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(uint32_t));
296 memcpy(&count
, ptr
, sizeof(uint8_t));
297 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(uint8_t));
298 for(i
= 0; i
< count
&& i
< (unsigned int)nfds
; i
++)
300 rb_fde_t
*tF
= make_fde_from_wsaprotocol_info(ptr
);
304 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(WSAPROTOCOL_INFO
));
306 memcpy(&datalen
, ptr
, sizeof(size_t));
307 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(size_t));
308 retlen
= MYMIN(datalen
, datasize
);
309 memcpy(data
, ptr
, datalen
);
313 static LRESULT CALLBACK
314 rb_process_events(HWND nhwnd
, UINT umsg
, WPARAM wparam
, LPARAM lparam
)
323 F
= rb_find_fd(wparam
);
325 if(F
!= NULL
&& IsFDOpen(F
))
327 switch (WSAGETSELECTEVENT(lparam
))
333 if((hdl
= F
->read_handler
) != NULL
)
335 F
->read_handler
= NULL
;
346 if((hdl
= F
->write_handler
) != NULL
)
348 F
->write_handler
= NULL
;
349 data
= F
->write_data
;
350 F
->write_data
= NULL
;
366 return DefWindowProc(nhwnd
, umsg
, wparam
, lparam
);
372 rb_init_netio_win32(void)
374 /* this muchly sucks, but i'm too lazy to do overlapped i/o, maybe someday... -androsyn */
376 static const char *classname
= "ircd-ratbox-class";
379 wc
.lpfnWndProc
= (WNDPROC
) rb_process_events
;
384 wc
.hbrBackground
= NULL
;
385 wc
.lpszMenuName
= NULL
;
386 wc
.lpszClassName
= classname
;
387 wc
.hInstance
= GetModuleHandle(NULL
);
389 if(!RegisterClass(&wc
))
390 rb_lib_die("cannot register window class");
392 hwnd
= CreateWindow(classname
, classname
, WS_POPUP
, CW_USEDEFAULT
,
393 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
394 (HWND
) NULL
, (HMENU
) NULL
, wc
.hInstance
, NULL
);
396 rb_lib_die("could not create window");
401 rb_sleep(unsigned int seconds
, unsigned int useconds
)
403 DWORD msec
= seconds
* 1000;;
408 rb_setup_fd_win32(rb_fde_t
*F
)
413 SetHandleInformation((HANDLE
) F
->fd
, HANDLE_FLAG_INHERIT
, 0);
419 if(ioctlsocket((SOCKET
) F
->fd
, FIONBIO
, &nonb
) == -1)
433 rb_setselect_win32(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
435 int old_flags
= F
->pflags
;
437 lrb_assert(IsFDOpen(F
));
439 /* Update the list, even though we're not using it .. */
440 if(type
& RB_SELECT_READ
)
443 F
->pflags
|= FD_CLOSE
| FD_READ
| FD_ACCEPT
;
445 F
->pflags
&= ~(FD_CLOSE
| FD_READ
| FD_ACCEPT
);
446 F
->read_handler
= handler
;
447 F
->read_data
= client_data
;
450 if(type
& RB_SELECT_WRITE
)
453 F
->pflags
|= FD_WRITE
| FD_CONNECT
;
455 F
->pflags
&= ~(FD_WRITE
| FD_CONNECT
);
456 F
->write_handler
= handler
;
457 F
->write_data
= client_data
;
460 if(old_flags
== 0 && F
->pflags
== 0)
463 if(F
->pflags
!= old_flags
)
465 WSAAsyncSelect(F
->fd
, hwnd
, WM_SOCKET
, F
->pflags
);
471 static int has_set_timer
= 0;
474 rb_select_win32(long delay
)
477 if(has_set_timer
== 0)
479 /* XXX should probably have this handle all the events
480 * instead of busy looping
482 SetTimer(hwnd
, 0, delay
, NULL
);
486 if(GetMessage(&msg
, NULL
, 0, 0) == FALSE
)
488 rb_lib_die("GetMessage failed..byebye");
492 DispatchMessage(&msg
);
501 _rb_strerror(int error
)
508 return "Interrupted system call";
510 return "Bad file number";
512 return "Permission denied";
514 return "Bad address";
516 return "Invalid argument";
518 return "Too many open sockets";
520 return "Operation would block";
522 return "Operation now in progress";
524 return "Operation already in progress";
526 return "Socket operation on non-socket";
527 case WSAEDESTADDRREQ
:
528 return "Destination address required";
530 return "Message too long";
532 return "Protocol wrong type for socket";
534 return "Bad protocol option";
535 case WSAEPROTONOSUPPORT
:
536 return "Protocol not supported";
537 case WSAESOCKTNOSUPPORT
:
538 return "Socket type not supported";
540 return "Operation not supported on socket";
541 case WSAEPFNOSUPPORT
:
542 return "Protocol family not supported";
543 case WSAEAFNOSUPPORT
:
544 return "Address family not supported";
546 return "Address already in use";
547 case WSAEADDRNOTAVAIL
:
548 return "Can't assign requested address";
550 return "Network is down";
552 return "Network is unreachable";
554 return "Net connection reset";
555 case WSAECONNABORTED
:
556 return "Software caused connection abort";
558 return "Connection reset by peer";
560 return "No buffer space available";
562 return "Socket is already connected";
564 return "Socket is not connected";
566 return "Can't send after socket shutdown";
567 case WSAETOOMANYREFS
:
568 return "Too many references, can't splice";
570 return "Connection timed out";
571 case WSAECONNREFUSED
:
572 return "Connection refused";
574 return "Too many levels of symbolic links";
575 case WSAENAMETOOLONG
:
576 return "File name too long";
578 return "Host is down";
579 case WSAEHOSTUNREACH
:
580 return "No route to host";
582 return "Directory not empty";
584 return "Too many processes";
586 return "Too many users";
588 return "Disc quota exceeded";
590 return "Stale NFS file handle";
592 return "Too many levels of remote in path";
594 return "Network system is unavailable";
595 case WSAVERNOTSUPPORTED
:
596 return "Winsock version out of range";
597 case WSANOTINITIALISED
:
598 return "WSAStartup not yet called";
600 return "Graceful shutdown in progress";
601 case WSAHOST_NOT_FOUND
:
602 return "Host not found";
604 return "No host data of that type was found";
606 return strerror(error
);
611 rb_strerror(int error
)
613 static char buf
[128];
614 rb_strlcpy(buf
, _rb_strerror(error
), sizeof(buf
));
617 #else /* win32 not supported */
619 rb_init_netio_win32(void)
626 rb_setselect_win32(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
633 rb_select_win32(long delay
)
640 rb_setup_fd_win32(rb_fde_t
*F
)