]>
jfr.im git - solanum.git/blob - librb/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
28 #include <librb_config.h>
30 #include <commio-int.h>
36 #define WM_SOCKET WM_USER
38 * having gettimeofday is nice...
43 unsigned __int64 ft_i64
;
48 #define Const64(x) x##LL
50 #define Const64(x) x##i64
52 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
53 #define EPOCH_BIAS Const64(116444736000000000)
58 return GetCurrentProcessId();
63 rb_gettimeofday(struct timeval
*tp
, void *not_used
)
67 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
68 GetSystemTimeAsFileTime(&ft
.ft_val
);
70 /* seconds since epoch */
71 tp
->tv_sec
= (long)((ft
.ft_i64
- EPOCH_BIAS
) / Const64(10000000));
73 /* microseconds remaining */
74 tp
->tv_usec
= (long)((ft
.ft_i64
/ Const64(10)) % Const64(1000000));
81 rb_spawn_process(const char *path
, const char **argv
)
83 PROCESS_INFORMATION pi
;
86 memset(&pi
, 0, sizeof(pi
));
87 memset(&si
, 0, sizeof(si
));
88 rb_strlcpy(cmd
, path
, sizeof(cmd
));
89 if(CreateProcess(cmd
, cmd
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
) == FALSE
)
92 return (pi
.dwProcessId
);
96 rb_waitpid(pid_t pid
, int *status
, int flags
)
98 DWORD timeout
= (flags
& WNOHANG
) ? 0 : INFINITE
;
102 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, pid
);
105 waitcode
= WaitForSingleObject(hProcess
, timeout
);
106 if(waitcode
== WAIT_TIMEOUT
)
108 CloseHandle(hProcess
);
111 else if(waitcode
== WAIT_OBJECT_0
)
113 if(GetExitCodeProcess(hProcess
, &waitcode
))
115 *status
= (int)((waitcode
& 0xff) << 8);
116 CloseHandle(hProcess
);
120 CloseHandle(hProcess
);
129 rb_setenv(const char *name
, const char *value
, int overwrite
)
135 if((buf
= getenv(name
)) != NULL
)
143 if(name
== NULL
|| value
== NULL
)
145 len
= strlen(name
) + strlen(value
) + 5;
146 buf
= rb_malloc(len
);
147 snprintf(buf
, len
, "%s=%s", name
, value
);
154 rb_kill(pid_t pid
, int sig
)
158 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, pid
);
169 if(TerminateProcess(hProcess
, sig
))
173 CloseHandle(hProcess
);
186 uint8_t protocol count
187 WSAPROTOCOL_INFO * count
194 make_wsaprotocol_info(pid_t process
, rb_fde_t
*F
, WSAPROTOCOL_INFO
* inf
)
196 WSAPROTOCOL_INFO info
;
197 if(!WSADuplicateSocket((SOCKET
) rb_get_fd(F
), process
, &info
))
199 memcpy(inf
, &info
, sizeof(WSAPROTOCOL_INFO
));
206 make_fde_from_wsaprotocol_info(void *data
)
208 WSAPROTOCOL_INFO
*info
= data
;
210 t
= WSASocket(FROM_PROTOCOL_INFO
, FROM_PROTOCOL_INFO
, FROM_PROTOCOL_INFO
, info
, 0, 0);
211 if(t
== INVALID_SOCKET
)
216 return rb_open(t
, RB_FD_SOCKET
, "remote_socket");
219 static uint8_t fd_buf
[16384];
220 #define MAGIC_CONTROL 0xFF0ACAFE
223 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)
226 sizeof(uint32_t) + sizeof(uint8_t) + (sizeof(WSAPROTOCOL_INFO
) * (size_t)count
) +
227 sizeof(size_t) + datasize
;
229 uint32_t magic
= MAGIC_CONTROL
;
236 if(bufsize
> sizeof(fd_buf
))
241 memset(fd_buf
, 0, sizeof(fd_buf
));
244 memcpy(ptr
, &magic
, sizeof(magic
));
245 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(magic
));
246 *((uint8_t *)ptr
) = count
;
247 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(uint8_t));
249 for(i
= 0; i
< count
; i
++)
251 make_wsaprotocol_info(pid
, F
[i
], (WSAPROTOCOL_INFO
*) ptr
);
252 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(WSAPROTOCOL_INFO
));
254 memcpy(ptr
, &datasize
, sizeof(size_t));
255 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(size_t));
256 memcpy(ptr
, data
, datasize
);
257 return rb_write(xF
, fd_buf
, bufsize
);
263 #define MYMIN(a, b) ((a) < (b) ? (a) : (b))
266 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
268 size_t minsize
= sizeof(uint32_t) + sizeof(uint8_t) + sizeof(size_t);
276 memset(fd_buf
, 0, sizeof(fd_buf
)); /* some paranoia here... */
277 ret
= rb_read(F
, fd_buf
, sizeof(fd_buf
));
282 if(ret
< (ssize_t
) minsize
)
288 memcpy(&magic
, ptr
, sizeof(uint32_t));
289 if(magic
!= MAGIC_CONTROL
)
294 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(uint32_t));
295 memcpy(&count
, ptr
, sizeof(uint8_t));
296 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(uint8_t));
297 for(i
= 0; i
< count
&& i
< (unsigned int)nfds
; i
++)
299 rb_fde_t
*tF
= make_fde_from_wsaprotocol_info(ptr
);
303 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(WSAPROTOCOL_INFO
));
305 memcpy(&datalen
, ptr
, sizeof(size_t));
306 ptr
= (void *)((uintptr_t)ptr
+ (uintptr_t)sizeof(size_t));
307 retlen
= MYMIN(datalen
, datasize
);
308 memcpy(data
, ptr
, datalen
);
312 static LRESULT CALLBACK
313 rb_process_events(HWND nhwnd
, UINT umsg
, WPARAM wparam
, LPARAM lparam
)
322 F
= rb_find_fd(wparam
);
324 if(F
!= NULL
&& IsFDOpen(F
))
326 switch (WSAGETSELECTEVENT(lparam
))
332 if((hdl
= F
->read_handler
) != NULL
)
334 F
->read_handler
= NULL
;
345 if((hdl
= F
->write_handler
) != NULL
)
347 F
->write_handler
= NULL
;
348 data
= F
->write_data
;
349 F
->write_data
= NULL
;
365 return DefWindowProc(nhwnd
, umsg
, wparam
, lparam
);
371 rb_init_netio_win32(void)
373 /* this muchly sucks, but i'm too lazy to do overlapped i/o, maybe someday... -androsyn */
375 static const char *classname
= "solanum-class";
378 wc
.lpfnWndProc
= (WNDPROC
) rb_process_events
;
383 wc
.hbrBackground
= NULL
;
384 wc
.lpszMenuName
= NULL
;
385 wc
.lpszClassName
= classname
;
386 wc
.hInstance
= GetModuleHandle(NULL
);
388 if(!RegisterClass(&wc
))
389 rb_lib_die("cannot register window class");
391 hwnd
= CreateWindow(classname
, classname
, WS_POPUP
, CW_USEDEFAULT
,
392 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
393 (HWND
) NULL
, (HMENU
) NULL
, wc
.hInstance
, NULL
);
395 rb_lib_die("could not create window");
400 rb_sleep(unsigned int seconds
, unsigned int useconds
)
402 DWORD msec
= seconds
* 1000;;
407 rb_setup_fd_win32(rb_fde_t
*F
)
412 SetHandleInformation((HANDLE
) F
->fd
, HANDLE_FLAG_INHERIT
, 0);
413 if (F
->type
& RB_FD_SOCKET
) {
414 unsigned long nonb
= 1;
415 if (ioctlsocket((SOCKET
) F
->fd
, FIONBIO
, &nonb
) == -1) {
424 rb_setselect_win32(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
426 int old_flags
= F
->pflags
;
428 lrb_assert(IsFDOpen(F
));
430 /* Update the list, even though we're not using it .. */
431 if(type
& RB_SELECT_READ
)
434 F
->pflags
|= FD_CLOSE
| FD_READ
| FD_ACCEPT
;
436 F
->pflags
&= ~(FD_CLOSE
| FD_READ
| FD_ACCEPT
);
437 F
->read_handler
= handler
;
438 F
->read_data
= client_data
;
441 if(type
& RB_SELECT_WRITE
)
444 F
->pflags
|= FD_WRITE
| FD_CONNECT
;
446 F
->pflags
&= ~(FD_WRITE
| FD_CONNECT
);
447 F
->write_handler
= handler
;
448 F
->write_data
= client_data
;
451 if(old_flags
== 0 && F
->pflags
== 0)
454 if(F
->pflags
!= old_flags
)
456 WSAAsyncSelect(F
->fd
, hwnd
, WM_SOCKET
, F
->pflags
);
462 static int has_set_timer
= 0;
465 rb_select_win32(long delay
)
468 if(has_set_timer
== 0)
470 /* XXX should probably have this handle all the events
471 * instead of busy looping
473 SetTimer(hwnd
, 0, delay
, NULL
);
477 if(GetMessage(&msg
, NULL
, 0, 0) == FALSE
)
479 rb_lib_die("GetMessage failed..byebye");
483 DispatchMessage(&msg
);
492 _rb_strerror(int error
)
499 return "Interrupted system call";
501 return "Bad file number";
503 return "Permission denied";
505 return "Bad address";
507 return "Invalid argument";
509 return "Too many open sockets";
511 return "Operation would block";
513 return "Operation now in progress";
515 return "Operation already in progress";
517 return "Socket operation on non-socket";
518 case WSAEDESTADDRREQ
:
519 return "Destination address required";
521 return "Message too long";
523 return "Protocol wrong type for socket";
525 return "Bad protocol option";
526 case WSAEPROTONOSUPPORT
:
527 return "Protocol not supported";
528 case WSAESOCKTNOSUPPORT
:
529 return "Socket type not supported";
531 return "Operation not supported on socket";
532 case WSAEPFNOSUPPORT
:
533 return "Protocol family not supported";
534 case WSAEAFNOSUPPORT
:
535 return "Address family not supported";
537 return "Address already in use";
538 case WSAEADDRNOTAVAIL
:
539 return "Can't assign requested address";
541 return "Network is down";
543 return "Network is unreachable";
545 return "Net connection reset";
546 case WSAECONNABORTED
:
547 return "Software caused connection abort";
549 return "Connection reset by peer";
551 return "No buffer space available";
553 return "Socket is already connected";
555 return "Socket is not connected";
557 return "Can't send after socket shutdown";
558 case WSAETOOMANYREFS
:
559 return "Too many references, can't splice";
561 return "Connection timed out";
562 case WSAECONNREFUSED
:
563 return "Connection refused";
565 return "Too many levels of symbolic links";
566 case WSAENAMETOOLONG
:
567 return "File name too long";
569 return "Host is down";
570 case WSAEHOSTUNREACH
:
571 return "No route to host";
573 return "Directory not empty";
575 return "Too many processes";
577 return "Too many users";
579 return "Disc quota exceeded";
581 return "Stale NFS file handle";
583 return "Too many levels of remote in path";
585 return "Network system is unavailable";
586 case WSAVERNOTSUPPORTED
:
587 return "Winsock version out of range";
588 case WSANOTINITIALISED
:
589 return "WSAStartup not yet called";
591 return "Graceful shutdown in progress";
592 case WSAHOST_NOT_FOUND
:
593 return "Host not found";
595 return "No host data of that type was found";
597 return strerror(error
);
602 rb_strerror(int error
)
604 static char buf
[128];
605 rb_strlcpy(buf
, _rb_strerror(error
), sizeof(buf
));
610 rb_path_to_self(void)
612 static char path_buf
[MAX_PATH
];
613 GetModuleFileName(NULL
, path_buf
, MAX_PATH
);
617 #else /* win32 not supported */
619 rb_init_netio_win32(void)
626 rb_setselect_win32(rb_fde_t
*F
__attribute__((unused
)), unsigned int type
__attribute__((unused
)), PF
* handler
__attribute__((unused
)), void *client_data
__attribute__((unused
)))
633 rb_select_win32(long delay
__attribute__((unused
)))
640 rb_setup_fd_win32(rb_fde_t
*F
__attribute__((unused
)))