4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
7 * Copyright 2006 Mike McCormack
8 * Copyright 2006 Damjan Jovanovic
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include <sys/types.h>
35 #if defined(__MINGW32__) || defined (_MSC_VER)
36 # include <ws2tcpip.h>
38 # define EADDRINUSE WSAEADDRINUSE
41 # define EAGAIN WSAEWOULDBLOCK
49 # ifdef HAVE_SYS_SOCKET_H
50 # include <sys/socket.h>
52 # ifdef HAVE_NETINET_IN_H
53 # include <netinet/in.h>
55 # ifdef HAVE_NETINET_TCP_H
56 # include <netinet/tcp.h>
58 # ifdef HAVE_ARPA_INET_H
59 # include <arpa/inet.h>
64 # ifdef HAVE_SYS_POLL_H
65 # include <sys/poll.h>
67 # ifdef HAVE_SYS_FILIO_H
68 # include <sys/filio.h>
70 # ifdef HAVE_SYS_IOCTL_H
71 # include <sys/ioctl.h>
73 # define closesocket close
74 # define ioctlsocket ioctl
75 #endif /* defined(__MINGW32__) || defined (_MSC_VER) */
83 #include "wine/unicode.h"
88 #include "wine/debug.h"
90 #include "rpc_binding.h"
91 #include "rpc_assoc.h"
92 #include "rpc_message.h"
93 #include "rpc_server.h"
94 #include "epm_towers.h"
97 # define SOL_TCP IPPROTO_TCP
100 WINE_DEFAULT_DEBUG_CHANNEL(rpc
);
102 static RPC_STATUS
RPCRT4_SpawnConnection(RpcConnection
** Connection
, RpcConnection
* OldConnection
);
104 /**** ncacn_np support ****/
106 typedef struct _RpcConnection_np
108 RpcConnection common
;
114 static RpcConnection
*rpcrt4_conn_np_alloc(void)
116 RpcConnection_np
*npc
= HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np
));
120 memset(&npc
->ovl
, 0, sizeof(npc
->ovl
));
121 npc
->listening
= FALSE
;
126 static RPC_STATUS
rpcrt4_conn_listen_pipe(RpcConnection_np
*npc
)
131 npc
->listening
= TRUE
;
134 if (ConnectNamedPipe(npc
->pipe
, &npc
->ovl
[0]))
137 switch(GetLastError())
139 case ERROR_PIPE_CONNECTED
:
140 SetEvent(npc
->ovl
[0].hEvent
);
142 case ERROR_IO_PENDING
:
143 /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */
145 case ERROR_NO_DATA_DETECTED
:
146 /* client has disconnected, retry */
147 DisconnectNamedPipe( npc
->pipe
);
150 npc
->listening
= FALSE
;
151 WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());
152 return RPC_S_OUT_OF_RESOURCES
;
157 static RPC_STATUS
rpcrt4_conn_create_pipe(RpcConnection
*Connection
, LPCSTR pname
)
159 RpcConnection_np
*npc
= (RpcConnection_np
*) Connection
;
160 TRACE("listening on %s\n", pname
);
162 npc
->pipe
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
163 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
,
164 PIPE_UNLIMITED_INSTANCES
,
165 RPC_MAX_PACKET_SIZE
, RPC_MAX_PACKET_SIZE
, 5000, NULL
);
166 if (npc
->pipe
== INVALID_HANDLE_VALUE
) {
167 WARN("CreateNamedPipe failed with error %d\n", GetLastError());
168 if (GetLastError() == ERROR_FILE_EXISTS
)
169 return RPC_S_DUPLICATE_ENDPOINT
;
171 return RPC_S_CANT_CREATE_ENDPOINT
;
174 memset(&npc
->ovl
, 0, sizeof(npc
->ovl
));
175 npc
->ovl
[0].hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
176 npc
->ovl
[1].hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
178 /* Note: we don't call ConnectNamedPipe here because it must be done in the
179 * server thread as the thread must be alertable */
183 static RPC_STATUS
rpcrt4_conn_open_pipe(RpcConnection
*Connection
, LPCSTR pname
, BOOL wait
)
185 RpcConnection_np
*npc
= (RpcConnection_np
*) Connection
;
189 TRACE("connecting to %s\n", pname
);
195 dwFlags
= SECURITY_SQOS_PRESENT
;
196 switch (Connection
->QOS
->qos
->ImpersonationType
)
198 case RPC_C_IMP_LEVEL_DEFAULT
:
199 /* FIXME: what to do here? */
201 case RPC_C_IMP_LEVEL_ANONYMOUS
:
202 dwFlags
|= SECURITY_ANONYMOUS
;
204 case RPC_C_IMP_LEVEL_IDENTIFY
:
205 dwFlags
|= SECURITY_IDENTIFICATION
;
207 case RPC_C_IMP_LEVEL_IMPERSONATE
:
208 dwFlags
|= SECURITY_IMPERSONATION
;
210 case RPC_C_IMP_LEVEL_DELEGATE
:
211 dwFlags
|= SECURITY_DELEGATION
;
214 if (Connection
->QOS
->qos
->IdentityTracking
== RPC_C_QOS_IDENTITY_DYNAMIC
)
215 dwFlags
|= SECURITY_CONTEXT_TRACKING
;
217 pipe
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
218 OPEN_EXISTING
, dwFlags
, 0);
219 if (pipe
!= INVALID_HANDLE_VALUE
) break;
220 err
= GetLastError();
221 if (err
== ERROR_PIPE_BUSY
) {
222 TRACE("connection failed, error=%x\n", err
);
223 return RPC_S_SERVER_TOO_BUSY
;
225 if (!wait
|| !WaitNamedPipeA(pname
, NMPWAIT_WAIT_FOREVER
)) {
226 err
= GetLastError();
227 WARN("connection failed, error=%x\n", err
);
228 return RPC_S_SERVER_UNAVAILABLE
;
233 memset(&npc
->ovl
, 0, sizeof(npc
->ovl
));
234 /* pipe is connected; change to message-read mode. */
235 dwMode
= PIPE_READMODE_MESSAGE
;
236 SetNamedPipeHandleState(pipe
, &dwMode
, NULL
, NULL
);
237 npc
->ovl
[0].hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
238 npc
->ovl
[1].hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
244 static RPC_STATUS
rpcrt4_ncalrpc_open(RpcConnection
* Connection
)
246 RpcConnection_np
*npc
= (RpcConnection_np
*) Connection
;
247 static const char prefix
[] = "\\\\.\\pipe\\lrpc\\";
251 /* already connected? */
255 /* protseq=ncalrpc: supposed to use NT LPC ports,
256 * but we'll implement it with named pipes for now */
257 pname
= I_RpcAllocate(strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
258 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
259 r
= rpcrt4_conn_open_pipe(Connection
, pname
, TRUE
);
265 static RPC_STATUS
rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq
* protseq
, LPSTR endpoint
)
267 static const char prefix
[] = "\\\\.\\pipe\\lrpc\\";
270 RpcConnection
*Connection
;
271 char generated_endpoint
[22];
275 static LONG lrpc_nameless_id
;
276 DWORD process_id
= GetCurrentProcessId();
277 ULONG id
= InterlockedIncrement(&lrpc_nameless_id
);
278 snprintf(generated_endpoint
, sizeof(generated_endpoint
),
279 "LRPC%08x.%08x", process_id
, id
);
280 endpoint
= generated_endpoint
;
283 r
= RPCRT4_CreateConnection(&Connection
, TRUE
, protseq
->Protseq
, NULL
,
284 endpoint
, NULL
, NULL
, NULL
);
288 /* protseq=ncalrpc: supposed to use NT LPC ports,
289 * but we'll implement it with named pipes for now */
290 pname
= I_RpcAllocate(strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
291 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
292 r
= rpcrt4_conn_create_pipe(Connection
, pname
);
295 EnterCriticalSection(&protseq
->cs
);
296 Connection
->Next
= protseq
->conn
;
297 protseq
->conn
= Connection
;
298 LeaveCriticalSection(&protseq
->cs
);
303 static RPC_STATUS
rpcrt4_ncacn_np_open(RpcConnection
* Connection
)
305 RpcConnection_np
*npc
= (RpcConnection_np
*) Connection
;
306 static const char prefix
[] = "\\\\.";
310 /* already connected? */
314 /* protseq=ncacn_np: named pipes */
315 pname
= I_RpcAllocate(strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
316 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
317 r
= rpcrt4_conn_open_pipe(Connection
, pname
, FALSE
);
323 static RPC_STATUS
rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq
*protseq
, LPSTR endpoint
)
325 static const char prefix
[] = "\\\\.";
328 RpcConnection
*Connection
;
329 char generated_endpoint
[21];
333 static LONG np_nameless_id
;
334 DWORD process_id
= GetCurrentProcessId();
335 ULONG id
= InterlockedExchangeAdd(&np_nameless_id
, 1 );
336 snprintf(generated_endpoint
, sizeof(generated_endpoint
),
337 "\\\\pipe\\\\%08x.%03x", process_id
, id
);
338 endpoint
= generated_endpoint
;
341 r
= RPCRT4_CreateConnection(&Connection
, TRUE
, protseq
->Protseq
, NULL
,
342 endpoint
, NULL
, NULL
, NULL
);
346 /* protseq=ncacn_np: named pipes */
347 pname
= I_RpcAllocate(strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
348 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
349 r
= rpcrt4_conn_create_pipe(Connection
, pname
);
352 EnterCriticalSection(&protseq
->cs
);
353 Connection
->Next
= protseq
->conn
;
354 protseq
->conn
= Connection
;
355 LeaveCriticalSection(&protseq
->cs
);
360 static void rpcrt4_conn_np_handoff(RpcConnection_np
*old_npc
, RpcConnection_np
*new_npc
)
362 /* because of the way named pipes work, we'll transfer the connected pipe
363 * to the child, then reopen the server binding to continue listening */
365 new_npc
->pipe
= old_npc
->pipe
;
366 new_npc
->ovl
[0] = old_npc
->ovl
[0];
367 new_npc
->ovl
[1] = old_npc
->ovl
[1];
369 memset(&old_npc
->ovl
, 0, sizeof(old_npc
->ovl
));
370 old_npc
->listening
= FALSE
;
373 static RPC_STATUS
rpcrt4_ncacn_np_handoff(RpcConnection
*old_conn
, RpcConnection
*new_conn
)
377 static const char prefix
[] = "\\\\.";
379 rpcrt4_conn_np_handoff((RpcConnection_np
*)old_conn
, (RpcConnection_np
*)new_conn
);
381 pname
= I_RpcAllocate(strlen(prefix
) + strlen(old_conn
->Endpoint
) + 1);
382 strcat(strcpy(pname
, prefix
), old_conn
->Endpoint
);
383 status
= rpcrt4_conn_create_pipe(old_conn
, pname
);
389 static RPC_STATUS
rpcrt4_ncalrpc_handoff(RpcConnection
*old_conn
, RpcConnection
*new_conn
)
393 static const char prefix
[] = "\\\\.\\pipe\\lrpc\\";
395 TRACE("%s\n", old_conn
->Endpoint
);
397 rpcrt4_conn_np_handoff((RpcConnection_np
*)old_conn
, (RpcConnection_np
*)new_conn
);
399 pname
= I_RpcAllocate(strlen(prefix
) + strlen(old_conn
->Endpoint
) + 1);
400 strcat(strcpy(pname
, prefix
), old_conn
->Endpoint
);
401 status
= rpcrt4_conn_create_pipe(old_conn
, pname
);
407 static int rpcrt4_conn_np_read(RpcConnection
*Connection
,
408 void *buffer
, unsigned int count
)
410 RpcConnection_np
*npc
= (RpcConnection_np
*) Connection
;
413 unsigned int bytes_left
= count
;
418 ret
= ReadFile(npc
->pipe
, buf
, bytes_left
, &bytes_read
, &npc
->ovl
[0]);
419 if ((!ret
|| !bytes_read
) && (GetLastError() != ERROR_IO_PENDING
))
422 ret
= GetOverlappedResult(npc
->pipe
, &npc
->ovl
[0], &bytes_read
, TRUE
);
423 if (!ret
&& (GetLastError() != ERROR_MORE_DATA
))
426 bytes_left
-= bytes_read
;
429 return ret
? count
: -1;
432 static int rpcrt4_conn_np_write(RpcConnection
*Connection
,
433 const void *buffer
, unsigned int count
)
435 RpcConnection_np
*npc
= (RpcConnection_np
*) Connection
;
436 const char *buf
= buffer
;
438 unsigned int bytes_left
= count
;
443 ret
= WriteFile(npc
->pipe
, buf
, bytes_left
, &bytes_written
, &npc
->ovl
[1]);
444 if ((!ret
|| !bytes_written
) && (GetLastError() != ERROR_IO_PENDING
))
447 ret
= GetOverlappedResult(npc
->pipe
, &npc
->ovl
[1], &bytes_written
, TRUE
);
448 if (!ret
&& (GetLastError() != ERROR_MORE_DATA
))
451 bytes_left
-= bytes_written
;
452 buf
+= bytes_written
;
454 return ret
? count
: -1;
457 static int rpcrt4_conn_np_close(RpcConnection
*Connection
)
459 RpcConnection_np
*npc
= (RpcConnection_np
*) Connection
;
461 FlushFileBuffers(npc
->pipe
);
462 CloseHandle(npc
->pipe
);
465 if (npc
->ovl
[0].hEvent
) {
466 CloseHandle(npc
->ovl
[0].hEvent
);
467 npc
->ovl
[0].hEvent
= 0;
469 if (npc
->ovl
[1].hEvent
) {
470 CloseHandle(npc
->ovl
[1].hEvent
);
471 npc
->ovl
[1].hEvent
= 0;
476 static void rpcrt4_conn_np_cancel_call(RpcConnection
*Connection
)
478 /* FIXME: implement when named pipe writes use overlapped I/O */
481 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection
*Connection
)
483 /* FIXME: implement when named pipe writes use overlapped I/O */
487 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data
,
488 const char *networkaddr
,
489 const char *endpoint
)
491 twr_empty_floor_t
*smb_floor
;
492 twr_empty_floor_t
*nb_floor
;
494 size_t networkaddr_size
;
495 size_t endpoint_size
;
497 TRACE("(%p, %s, %s)\n", tower_data
, networkaddr
, endpoint
);
499 networkaddr_size
= networkaddr
? strlen(networkaddr
) + 1 : 1;
500 endpoint_size
= endpoint
? strlen(endpoint
) + 1 : 1;
501 size
= sizeof(*smb_floor
) + endpoint_size
+ sizeof(*nb_floor
) + networkaddr_size
;
506 smb_floor
= (twr_empty_floor_t
*)tower_data
;
508 tower_data
+= sizeof(*smb_floor
);
510 smb_floor
->count_lhs
= sizeof(smb_floor
->protid
);
511 smb_floor
->protid
= EPM_PROTOCOL_SMB
;
512 smb_floor
->count_rhs
= endpoint_size
;
515 memcpy(tower_data
, endpoint
, endpoint_size
);
518 tower_data
+= endpoint_size
;
520 nb_floor
= (twr_empty_floor_t
*)tower_data
;
522 tower_data
+= sizeof(*nb_floor
);
524 nb_floor
->count_lhs
= sizeof(nb_floor
->protid
);
525 nb_floor
->protid
= EPM_PROTOCOL_NETBIOS
;
526 nb_floor
->count_rhs
= networkaddr_size
;
529 memcpy(tower_data
, networkaddr
, networkaddr_size
);
536 static RPC_STATUS
rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data
,
541 const twr_empty_floor_t
*smb_floor
= (const twr_empty_floor_t
*)tower_data
;
542 const twr_empty_floor_t
*nb_floor
;
544 TRACE("(%p, %d, %p, %p)\n", tower_data
, (int)tower_size
, networkaddr
, endpoint
);
546 if (tower_size
< sizeof(*smb_floor
))
547 return EPT_S_NOT_REGISTERED
;
549 tower_data
+= sizeof(*smb_floor
);
550 tower_size
-= sizeof(*smb_floor
);
552 if ((smb_floor
->count_lhs
!= sizeof(smb_floor
->protid
)) ||
553 (smb_floor
->protid
!= EPM_PROTOCOL_SMB
) ||
554 (smb_floor
->count_rhs
> tower_size
) ||
555 (tower_data
[smb_floor
->count_rhs
- 1] != '\0'))
556 return EPT_S_NOT_REGISTERED
;
560 *endpoint
= I_RpcAllocate(smb_floor
->count_rhs
);
562 return RPC_S_OUT_OF_RESOURCES
;
563 memcpy(*endpoint
, tower_data
, smb_floor
->count_rhs
);
565 tower_data
+= smb_floor
->count_rhs
;
566 tower_size
-= smb_floor
->count_rhs
;
568 if (tower_size
< sizeof(*nb_floor
))
569 return EPT_S_NOT_REGISTERED
;
571 nb_floor
= (const twr_empty_floor_t
*)tower_data
;
573 tower_data
+= sizeof(*nb_floor
);
574 tower_size
-= sizeof(*nb_floor
);
576 if ((nb_floor
->count_lhs
!= sizeof(nb_floor
->protid
)) ||
577 (nb_floor
->protid
!= EPM_PROTOCOL_NETBIOS
) ||
578 (nb_floor
->count_rhs
> tower_size
) ||
579 (tower_data
[nb_floor
->count_rhs
- 1] != '\0'))
580 return EPT_S_NOT_REGISTERED
;
584 *networkaddr
= I_RpcAllocate(nb_floor
->count_rhs
);
589 I_RpcFree(*endpoint
);
592 return RPC_S_OUT_OF_RESOURCES
;
594 memcpy(*networkaddr
, tower_data
, nb_floor
->count_rhs
);
600 typedef struct _RpcServerProtseq_np
602 RpcServerProtseq common
;
604 } RpcServerProtseq_np
;
606 static RpcServerProtseq
*rpcrt4_protseq_np_alloc(void)
608 RpcServerProtseq_np
*ps
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ps
));
610 ps
->mgr_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
614 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq
*protseq
)
616 RpcServerProtseq_np
*npps
= CONTAINING_RECORD(protseq
, RpcServerProtseq_np
, common
);
617 SetEvent(npps
->mgr_event
);
620 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq
*protseq
, void *prev_array
, unsigned int *count
)
622 HANDLE
*objs
= prev_array
;
623 RpcConnection_np
*conn
;
624 RpcServerProtseq_np
*npps
= CONTAINING_RECORD(protseq
, RpcServerProtseq_np
, common
);
626 EnterCriticalSection(&protseq
->cs
);
628 /* open and count connections */
630 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_np
, common
);
632 rpcrt4_conn_listen_pipe(conn
);
633 if (conn
->ovl
[0].hEvent
)
635 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_np
, common
);
638 /* make array of connections */
640 objs
= HeapReAlloc(GetProcessHeap(), 0, objs
, *count
*sizeof(HANDLE
));
642 objs
= HeapAlloc(GetProcessHeap(), 0, *count
*sizeof(HANDLE
));
645 ERR("couldn't allocate objs\n");
646 LeaveCriticalSection(&protseq
->cs
);
650 objs
[0] = npps
->mgr_event
;
652 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_np
, common
);
654 if ((objs
[*count
] = conn
->ovl
[0].hEvent
))
656 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_np
, common
);
658 LeaveCriticalSection(&protseq
->cs
);
662 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq
*protseq
, void *array
)
664 HeapFree(GetProcessHeap(), 0, array
);
667 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq
*protseq
, unsigned int count
, void *wait_array
)
670 HANDLE
*objs
= wait_array
;
672 RpcConnection
*cconn
;
673 RpcConnection_np
*conn
;
680 /* an alertable wait isn't strictly necessary, but due to our
681 * overlapped I/O implementation in Wine we need to free some memory
682 * by the file user APC being called, even if no completion routine was
683 * specified at the time of starting the async operation */
684 res
= WaitForMultipleObjectsEx(count
, objs
, FALSE
, INFINITE
, TRUE
);
685 } while (res
== WAIT_IO_COMPLETION
);
687 if (res
== WAIT_OBJECT_0
)
689 else if (res
== WAIT_FAILED
)
691 ERR("wait failed with error %d\n", GetLastError());
696 b_handle
= objs
[res
- WAIT_OBJECT_0
];
697 /* find which connection got a RPC */
698 EnterCriticalSection(&protseq
->cs
);
699 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_np
, common
);
701 if (b_handle
== conn
->ovl
[0].hEvent
) break;
702 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_np
, common
);
706 RPCRT4_SpawnConnection(&cconn
, &conn
->common
);
708 ERR("failed to locate connection for handle %p\n", b_handle
);
709 LeaveCriticalSection(&protseq
->cs
);
712 RPCRT4_new_client(cconn
);
719 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data
,
720 const char *networkaddr
,
721 const char *endpoint
)
723 twr_empty_floor_t
*pipe_floor
;
725 size_t endpoint_size
;
727 TRACE("(%p, %s, %s)\n", tower_data
, networkaddr
, endpoint
);
729 endpoint_size
= strlen(endpoint
) + 1;
730 size
= sizeof(*pipe_floor
) + endpoint_size
;
735 pipe_floor
= (twr_empty_floor_t
*)tower_data
;
737 tower_data
+= sizeof(*pipe_floor
);
739 pipe_floor
->count_lhs
= sizeof(pipe_floor
->protid
);
740 pipe_floor
->protid
= EPM_PROTOCOL_PIPE
;
741 pipe_floor
->count_rhs
= endpoint_size
;
743 memcpy(tower_data
, endpoint
, endpoint_size
);
748 static RPC_STATUS
rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data
,
753 const twr_empty_floor_t
*pipe_floor
= (const twr_empty_floor_t
*)tower_data
;
755 TRACE("(%p, %d, %p, %p)\n", tower_data
, (int)tower_size
, networkaddr
, endpoint
);
757 if (tower_size
< sizeof(*pipe_floor
))
758 return EPT_S_NOT_REGISTERED
;
760 tower_data
+= sizeof(*pipe_floor
);
761 tower_size
-= sizeof(*pipe_floor
);
763 if ((pipe_floor
->count_lhs
!= sizeof(pipe_floor
->protid
)) ||
764 (pipe_floor
->protid
!= EPM_PROTOCOL_PIPE
) ||
765 (pipe_floor
->count_rhs
> tower_size
) ||
766 (tower_data
[pipe_floor
->count_rhs
- 1] != '\0'))
767 return EPT_S_NOT_REGISTERED
;
774 *endpoint
= I_RpcAllocate(pipe_floor
->count_rhs
);
776 return RPC_S_OUT_OF_RESOURCES
;
777 memcpy(*endpoint
, tower_data
, pipe_floor
->count_rhs
);
783 /**** ncacn_ip_tcp support ****/
785 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data
,
786 const char *networkaddr
,
787 unsigned char tcp_protid
,
788 const char *endpoint
)
790 twr_tcp_floor_t
*tcp_floor
;
791 twr_ipv4_floor_t
*ipv4_floor
;
793 struct addrinfo hints
;
795 size_t size
= sizeof(*tcp_floor
) + sizeof(*ipv4_floor
);
797 TRACE("(%p, %s, %s)\n", tower_data
, networkaddr
, endpoint
);
802 tcp_floor
= (twr_tcp_floor_t
*)tower_data
;
803 tower_data
+= sizeof(*tcp_floor
);
805 ipv4_floor
= (twr_ipv4_floor_t
*)tower_data
;
807 tcp_floor
->count_lhs
= sizeof(tcp_floor
->protid
);
808 tcp_floor
->protid
= tcp_protid
;
809 tcp_floor
->count_rhs
= sizeof(tcp_floor
->port
);
811 ipv4_floor
->count_lhs
= sizeof(ipv4_floor
->protid
);
812 ipv4_floor
->protid
= EPM_PROTOCOL_IP
;
813 ipv4_floor
->count_rhs
= sizeof(ipv4_floor
->ipv4addr
);
815 hints
.ai_flags
= AI_NUMERICHOST
;
816 /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
817 hints
.ai_family
= PF_INET
;
818 hints
.ai_socktype
= SOCK_STREAM
;
819 hints
.ai_protocol
= IPPROTO_TCP
;
820 hints
.ai_addrlen
= 0;
821 hints
.ai_addr
= NULL
;
822 hints
.ai_canonname
= NULL
;
823 hints
.ai_next
= NULL
;
825 ret
= getaddrinfo(networkaddr
, endpoint
, &hints
, &ai
);
828 ret
= getaddrinfo("0.0.0.0", endpoint
, &hints
, &ai
);
831 ERR("getaddrinfo failed: %s\n", gai_strerror(ret
));
836 if (ai
->ai_family
== PF_INET
)
838 const struct sockaddr_in
*sin
= (const struct sockaddr_in
*)ai
->ai_addr
;
839 tcp_floor
->port
= sin
->sin_port
;
840 ipv4_floor
->ipv4addr
= sin
->sin_addr
.s_addr
;
844 ERR("unexpected protocol family %d\n", ai
->ai_family
);
853 static RPC_STATUS
rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data
,
856 unsigned char tcp_protid
,
859 const twr_tcp_floor_t
*tcp_floor
= (const twr_tcp_floor_t
*)tower_data
;
860 const twr_ipv4_floor_t
*ipv4_floor
;
861 struct in_addr in_addr
;
863 TRACE("(%p, %d, %p, %p)\n", tower_data
, (int)tower_size
, networkaddr
, endpoint
);
865 if (tower_size
< sizeof(*tcp_floor
))
866 return EPT_S_NOT_REGISTERED
;
868 tower_data
+= sizeof(*tcp_floor
);
869 tower_size
-= sizeof(*tcp_floor
);
871 if (tower_size
< sizeof(*ipv4_floor
))
872 return EPT_S_NOT_REGISTERED
;
874 ipv4_floor
= (const twr_ipv4_floor_t
*)tower_data
;
876 if ((tcp_floor
->count_lhs
!= sizeof(tcp_floor
->protid
)) ||
877 (tcp_floor
->protid
!= tcp_protid
) ||
878 (tcp_floor
->count_rhs
!= sizeof(tcp_floor
->port
)) ||
879 (ipv4_floor
->count_lhs
!= sizeof(ipv4_floor
->protid
)) ||
880 (ipv4_floor
->protid
!= EPM_PROTOCOL_IP
) ||
881 (ipv4_floor
->count_rhs
!= sizeof(ipv4_floor
->ipv4addr
)))
882 return EPT_S_NOT_REGISTERED
;
886 *endpoint
= I_RpcAllocate(6 /* sizeof("65535") + 1 */);
888 return RPC_S_OUT_OF_RESOURCES
;
889 sprintf(*endpoint
, "%u", ntohs(tcp_floor
->port
));
894 *networkaddr
= I_RpcAllocate(INET_ADDRSTRLEN
);
899 I_RpcFree(*endpoint
);
902 return RPC_S_OUT_OF_RESOURCES
;
904 in_addr
.s_addr
= ipv4_floor
->ipv4addr
;
905 if (!inet_ntop(AF_INET
, &in_addr
, *networkaddr
, INET_ADDRSTRLEN
))
907 ERR("inet_ntop: %s\n", strerror(errno
));
908 I_RpcFree(*networkaddr
);
912 I_RpcFree(*endpoint
);
915 return EPT_S_NOT_REGISTERED
;
922 typedef struct _RpcConnection_tcp
924 RpcConnection common
;
926 #ifdef HAVE_SOCKETPAIR
934 #ifdef HAVE_SOCKETPAIR
936 static BOOL
rpcrt4_sock_wait_init(RpcConnection_tcp
*tcpc
)
938 if (socketpair(PF_UNIX
, SOCK_STREAM
, 0, tcpc
->cancel_fds
) < 0)
940 ERR("socketpair() failed: %s\n", strerror(errno
));
946 static BOOL
rpcrt4_sock_wait_for_recv(RpcConnection_tcp
*tcpc
)
948 struct pollfd pfds
[2];
949 pfds
[0].fd
= tcpc
->sock
;
950 pfds
[0].events
= POLLIN
;
951 pfds
[1].fd
= tcpc
->cancel_fds
[0];
952 pfds
[1].events
= POLLIN
;
953 if (poll(pfds
, 2, -1 /* infinite */) == -1 && errno
!= EINTR
)
955 ERR("poll() failed: %s\n", strerror(errno
));
958 if (pfds
[1].revents
& POLLIN
) /* canceled */
961 read(pfds
[1].fd
, &dummy
, sizeof(dummy
));
967 static BOOL
rpcrt4_sock_wait_for_send(RpcConnection_tcp
*tcpc
)
971 pfd
.events
= POLLOUT
;
972 if (poll(&pfd
, 1, -1 /* infinite */) == -1 && errno
!= EINTR
)
974 ERR("poll() failed: %s\n", strerror(errno
));
980 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp
*tcpc
)
984 write(tcpc
->cancel_fds
[1], &dummy
, 1);
987 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp
*tcpc
)
989 close(tcpc
->cancel_fds
[0]);
990 close(tcpc
->cancel_fds
[1]);
993 #else /* HAVE_SOCKETPAIR */
995 static BOOL
rpcrt4_sock_wait_init(RpcConnection_tcp
*tcpc
)
997 static BOOL wsa_inited
;
1001 WSAStartup(MAKEWORD(2, 2), &wsadata
);
1002 /* Note: WSAStartup can be called more than once so we don't bother with
1003 * making accesses to wsa_inited thread-safe */
1006 tcpc
->sock_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1007 tcpc
->cancel_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1008 if (!tcpc
->sock_event
|| !tcpc
->cancel_event
)
1010 ERR("event creation failed\n");
1011 if (tcpc
->sock_event
) CloseHandle(tcpc
->sock_event
);
1017 static BOOL
rpcrt4_sock_wait_for_recv(RpcConnection_tcp
*tcpc
)
1019 HANDLE wait_handles
[2];
1021 if (WSAEventSelect(tcpc
->sock
, tcpc
->sock_event
, FD_READ
| FD_CLOSE
) == SOCKET_ERROR
)
1023 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1026 wait_handles
[0] = tcpc
->sock_event
;
1027 wait_handles
[1] = tcpc
->cancel_event
;
1028 res
= WaitForMultipleObjects(2, wait_handles
, FALSE
, INFINITE
);
1033 case WAIT_OBJECT_0
+ 1:
1036 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1041 static BOOL
rpcrt4_sock_wait_for_send(RpcConnection_tcp
*tcpc
)
1044 if (WSAEventSelect(tcpc
->sock
, tcpc
->sock_event
, FD_WRITE
| FD_CLOSE
) == SOCKET_ERROR
)
1046 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1049 res
= WaitForSingleObject(tcpc
->sock_event
, INFINITE
);
1055 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1060 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp
*tcpc
)
1062 SetEvent(tcpc
->cancel_event
);
1065 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp
*tcpc
)
1067 CloseHandle(tcpc
->sock_event
);
1068 CloseHandle(tcpc
->cancel_event
);
1073 static RpcConnection
*rpcrt4_conn_tcp_alloc(void)
1075 RpcConnection_tcp
*tcpc
;
1076 tcpc
= HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp
));
1080 if (!rpcrt4_sock_wait_init(tcpc
))
1082 HeapFree(GetProcessHeap(), 0, tcpc
);
1085 return &tcpc
->common
;
1088 static RPC_STATUS
rpcrt4_ncacn_ip_tcp_open(RpcConnection
* Connection
)
1090 RpcConnection_tcp
*tcpc
= (RpcConnection_tcp
*) Connection
;
1093 struct addrinfo
*ai
;
1094 struct addrinfo
*ai_cur
;
1095 struct addrinfo hints
;
1097 TRACE("(%s, %s)\n", Connection
->NetworkAddr
, Connection
->Endpoint
);
1099 if (tcpc
->sock
!= -1)
1103 hints
.ai_family
= PF_UNSPEC
;
1104 hints
.ai_socktype
= SOCK_STREAM
;
1105 hints
.ai_protocol
= IPPROTO_TCP
;
1106 hints
.ai_addrlen
= 0;
1107 hints
.ai_addr
= NULL
;
1108 hints
.ai_canonname
= NULL
;
1109 hints
.ai_next
= NULL
;
1111 ret
= getaddrinfo(Connection
->NetworkAddr
, Connection
->Endpoint
, &hints
, &ai
);
1114 ERR("getaddrinfo for %s:%s failed: %s\n", Connection
->NetworkAddr
,
1115 Connection
->Endpoint
, gai_strerror(ret
));
1116 return RPC_S_SERVER_UNAVAILABLE
;
1119 for (ai_cur
= ai
; ai_cur
; ai_cur
= ai_cur
->ai_next
)
1124 if (ai_cur
->ai_family
!= AF_INET
&& ai_cur
->ai_family
!= AF_INET6
)
1126 TRACE("skipping non-IP/IPv6 address family\n");
1134 getnameinfo(ai_cur
->ai_addr
, ai_cur
->ai_addrlen
,
1135 host
, sizeof(host
), service
, sizeof(service
),
1136 NI_NUMERICHOST
| NI_NUMERICSERV
);
1137 TRACE("trying %s:%s\n", host
, service
);
1140 sock
= socket(ai_cur
->ai_family
, ai_cur
->ai_socktype
, ai_cur
->ai_protocol
);
1143 WARN("socket() failed: %s\n", strerror(errno
));
1147 if (0>connect(sock
, ai_cur
->ai_addr
, ai_cur
->ai_addrlen
))
1149 WARN("connect() failed: %s\n", strerror(errno
));
1154 /* RPC depends on having minimal latency so disable the Nagle algorithm */
1156 setsockopt(sock
, SOL_TCP
, TCP_NODELAY
, (char *)&val
, sizeof(val
));
1158 ioctlsocket(sock
, FIONBIO
, &nonblocking
);
1163 TRACE("connected\n");
1168 ERR("couldn't connect to %s:%s\n", Connection
->NetworkAddr
, Connection
->Endpoint
);
1169 return RPC_S_SERVER_UNAVAILABLE
;
1172 static RPC_STATUS
rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq
*protseq
, LPSTR endpoint
)
1174 RPC_STATUS status
= RPC_S_CANT_CREATE_ENDPOINT
;
1177 struct addrinfo
*ai
;
1178 struct addrinfo
*ai_cur
;
1179 struct addrinfo hints
;
1180 RpcConnection
*first_connection
= NULL
;
1182 TRACE("(%p, %s)\n", protseq
, endpoint
);
1184 hints
.ai_flags
= AI_PASSIVE
/* for non-localhost addresses */;
1185 hints
.ai_family
= PF_UNSPEC
;
1186 hints
.ai_socktype
= SOCK_STREAM
;
1187 hints
.ai_protocol
= IPPROTO_TCP
;
1188 hints
.ai_addrlen
= 0;
1189 hints
.ai_addr
= NULL
;
1190 hints
.ai_canonname
= NULL
;
1191 hints
.ai_next
= NULL
;
1193 ret
= getaddrinfo(NULL
, endpoint
? endpoint
: "0", &hints
, &ai
);
1196 ERR("getaddrinfo for port %s failed: %s\n", endpoint
,
1198 if ((ret
== EAI_SERVICE
) || (ret
== EAI_NONAME
))
1199 return RPC_S_INVALID_ENDPOINT_FORMAT
;
1200 return RPC_S_CANT_CREATE_ENDPOINT
;
1203 for (ai_cur
= ai
; ai_cur
; ai_cur
= ai_cur
->ai_next
)
1205 RpcConnection_tcp
*tcpc
;
1206 RPC_STATUS create_status
;
1207 struct sockaddr_storage sa
;
1209 char service
[NI_MAXSERV
];
1212 if (ai_cur
->ai_family
!= AF_INET
&& ai_cur
->ai_family
!= AF_INET6
)
1214 TRACE("skipping non-IP/IPv6 address family\n");
1221 getnameinfo(ai_cur
->ai_addr
, ai_cur
->ai_addrlen
,
1222 host
, sizeof(host
), service
, sizeof(service
),
1223 NI_NUMERICHOST
| NI_NUMERICSERV
);
1224 TRACE("trying %s:%s\n", host
, service
);
1227 sock
= socket(ai_cur
->ai_family
, ai_cur
->ai_socktype
, ai_cur
->ai_protocol
);
1230 WARN("socket() failed: %s\n", strerror(errno
));
1231 status
= RPC_S_CANT_CREATE_ENDPOINT
;
1235 ret
= bind(sock
, ai_cur
->ai_addr
, ai_cur
->ai_addrlen
);
1238 WARN("bind failed: %s\n", strerror(errno
));
1240 if (errno
== EADDRINUSE
)
1241 status
= RPC_S_DUPLICATE_ENDPOINT
;
1243 status
= RPC_S_CANT_CREATE_ENDPOINT
;
1247 sa_len
= sizeof(sa
);
1248 if (getsockname(sock
, (struct sockaddr
*)&sa
, &sa_len
))
1250 WARN("getsockname() failed: %s\n", strerror(errno
));
1251 status
= RPC_S_CANT_CREATE_ENDPOINT
;
1255 ret
= getnameinfo((struct sockaddr
*)&sa
, sa_len
,
1256 NULL
, 0, service
, sizeof(service
),
1260 WARN("getnameinfo failed: %s\n", gai_strerror(ret
));
1261 status
= RPC_S_CANT_CREATE_ENDPOINT
;
1265 create_status
= RPCRT4_CreateConnection((RpcConnection
**)&tcpc
, TRUE
,
1266 protseq
->Protseq
, NULL
,
1267 service
, NULL
, NULL
, NULL
);
1268 if (create_status
!= RPC_S_OK
)
1271 status
= create_status
;
1276 ret
= listen(sock
, protseq
->MaxCalls
);
1279 WARN("listen failed: %s\n", strerror(errno
));
1280 RPCRT4_DestroyConnection(&tcpc
->common
);
1281 status
= RPC_S_OUT_OF_RESOURCES
;
1284 /* need a non-blocking socket, otherwise accept() has a potential
1285 * race-condition (poll() says it is readable, connection drops,
1286 * and accept() blocks until the next connection comes...)
1289 ret
= ioctlsocket(sock
, FIONBIO
, &nonblocking
);
1292 WARN("couldn't make socket non-blocking, error %d\n", ret
);
1293 RPCRT4_DestroyConnection(&tcpc
->common
);
1294 status
= RPC_S_OUT_OF_RESOURCES
;
1298 tcpc
->common
.Next
= first_connection
;
1299 first_connection
= &tcpc
->common
;
1301 /* since IPv4 and IPv6 share the same port space, we only need one
1302 * successful bind to listen for both */
1308 /* if at least one connection was created for an endpoint then
1310 if (first_connection
)
1312 RpcConnection
*conn
;
1314 /* find last element in list */
1315 for (conn
= first_connection
; conn
->Next
; conn
= conn
->Next
)
1318 EnterCriticalSection(&protseq
->cs
);
1319 conn
->Next
= protseq
->conn
;
1320 protseq
->conn
= first_connection
;
1321 LeaveCriticalSection(&protseq
->cs
);
1323 TRACE("listening on %s\n", endpoint
);
1327 ERR("couldn't listen on port %s\n", endpoint
);
1331 static RPC_STATUS
rpcrt4_conn_tcp_handoff(RpcConnection
*old_conn
, RpcConnection
*new_conn
)
1334 struct sockaddr_in address
;
1336 RpcConnection_tcp
*server
= (RpcConnection_tcp
*) old_conn
;
1337 RpcConnection_tcp
*client
= (RpcConnection_tcp
*) new_conn
;
1340 addrsize
= sizeof(address
);
1341 ret
= accept(server
->sock
, (struct sockaddr
*) &address
, &addrsize
);
1344 ERR("Failed to accept a TCP connection: error %d\n", ret
);
1345 return RPC_S_OUT_OF_RESOURCES
;
1348 ioctlsocket(ret
, FIONBIO
, &nonblocking
);
1350 TRACE("Accepted a new TCP connection\n");
1354 static int rpcrt4_conn_tcp_read(RpcConnection
*Connection
,
1355 void *buffer
, unsigned int count
)
1357 RpcConnection_tcp
*tcpc
= (RpcConnection_tcp
*) Connection
;
1359 while (bytes_read
!= count
)
1361 int r
= recv(tcpc
->sock
, (char *)buffer
+ bytes_read
, count
- bytes_read
, 0);
1366 else if (errno
!= EAGAIN
)
1368 WARN("recv() failed: %s\n", strerror(errno
));
1373 if (!rpcrt4_sock_wait_for_recv(tcpc
))
1377 TRACE("%d %p %u -> %d\n", tcpc
->sock
, buffer
, count
, bytes_read
);
1381 static int rpcrt4_conn_tcp_write(RpcConnection
*Connection
,
1382 const void *buffer
, unsigned int count
)
1384 RpcConnection_tcp
*tcpc
= (RpcConnection_tcp
*) Connection
;
1385 int bytes_written
= 0;
1386 while (bytes_written
!= count
)
1388 int r
= send(tcpc
->sock
, (const char *)buffer
+ bytes_written
, count
- bytes_written
, 0);
1391 else if (errno
!= EAGAIN
)
1395 if (!rpcrt4_sock_wait_for_send(tcpc
))
1399 TRACE("%d %p %u -> %d\n", tcpc
->sock
, buffer
, count
, bytes_written
);
1400 return bytes_written
;
1403 static int rpcrt4_conn_tcp_close(RpcConnection
*Connection
)
1405 RpcConnection_tcp
*tcpc
= (RpcConnection_tcp
*) Connection
;
1407 TRACE("%d\n", tcpc
->sock
);
1409 if (tcpc
->sock
!= -1)
1410 closesocket(tcpc
->sock
);
1412 rpcrt4_sock_wait_destroy(tcpc
);
1416 static void rpcrt4_conn_tcp_cancel_call(RpcConnection
*Connection
)
1418 RpcConnection_tcp
*tcpc
= (RpcConnection_tcp
*) Connection
;
1419 TRACE("%p\n", Connection
);
1420 rpcrt4_sock_wait_cancel(tcpc
);
1423 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection
*Connection
)
1425 RpcConnection_tcp
*tcpc
= (RpcConnection_tcp
*) Connection
;
1427 TRACE("%p\n", Connection
);
1429 if (!rpcrt4_sock_wait_for_recv(tcpc
))
1434 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data
,
1435 const char *networkaddr
,
1436 const char *endpoint
)
1438 return rpcrt4_ip_tcp_get_top_of_tower(tower_data
, networkaddr
,
1439 EPM_PROTOCOL_TCP
, endpoint
);
1442 #ifdef HAVE_SOCKETPAIR
1444 typedef struct _RpcServerProtseq_sock
1446 RpcServerProtseq common
;
1449 } RpcServerProtseq_sock
;
1451 static RpcServerProtseq
*rpcrt4_protseq_sock_alloc(void)
1453 RpcServerProtseq_sock
*ps
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ps
));
1457 if (!socketpair(PF_UNIX
, SOCK_DGRAM
, 0, fds
))
1459 fcntl(fds
[0], F_SETFL
, O_NONBLOCK
);
1460 fcntl(fds
[1], F_SETFL
, O_NONBLOCK
);
1461 ps
->mgr_event_rcv
= fds
[0];
1462 ps
->mgr_event_snd
= fds
[1];
1466 ERR("socketpair failed with error %s\n", strerror(errno
));
1467 HeapFree(GetProcessHeap(), 0, ps
);
1474 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq
*protseq
)
1476 RpcServerProtseq_sock
*sockps
= CONTAINING_RECORD(protseq
, RpcServerProtseq_sock
, common
);
1478 write(sockps
->mgr_event_snd
, &dummy
, sizeof(dummy
));
1481 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq
*protseq
, void *prev_array
, unsigned int *count
)
1483 struct pollfd
*poll_info
= prev_array
;
1484 RpcConnection_tcp
*conn
;
1485 RpcServerProtseq_sock
*sockps
= CONTAINING_RECORD(protseq
, RpcServerProtseq_sock
, common
);
1487 EnterCriticalSection(&protseq
->cs
);
1489 /* open and count connections */
1491 conn
= (RpcConnection_tcp
*)protseq
->conn
;
1493 if (conn
->sock
!= -1)
1495 conn
= (RpcConnection_tcp
*)conn
->common
.Next
;
1498 /* make array of connections */
1500 poll_info
= HeapReAlloc(GetProcessHeap(), 0, poll_info
, *count
*sizeof(*poll_info
));
1502 poll_info
= HeapAlloc(GetProcessHeap(), 0, *count
*sizeof(*poll_info
));
1505 ERR("couldn't allocate poll_info\n");
1506 LeaveCriticalSection(&protseq
->cs
);
1510 poll_info
[0].fd
= sockps
->mgr_event_rcv
;
1511 poll_info
[0].events
= POLLIN
;
1513 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_tcp
, common
);
1515 if (conn
->sock
!= -1)
1517 poll_info
[*count
].fd
= conn
->sock
;
1518 poll_info
[*count
].events
= POLLIN
;
1521 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_tcp
, common
);
1523 LeaveCriticalSection(&protseq
->cs
);
1527 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq
*protseq
, void *array
)
1529 HeapFree(GetProcessHeap(), 0, array
);
1532 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq
*protseq
, unsigned int count
, void *wait_array
)
1534 struct pollfd
*poll_info
= wait_array
;
1537 RpcConnection
*cconn
;
1538 RpcConnection_tcp
*conn
;
1543 ret
= poll(poll_info
, count
, -1);
1546 ERR("poll failed with error %d\n", ret
);
1550 for (i
= 0; i
< count
; i
++)
1551 if (poll_info
[i
].revents
& POLLIN
)
1553 /* RPC server event */
1557 read(poll_info
[0].fd
, &dummy
, sizeof(dummy
));
1561 /* find which connection got a RPC */
1562 EnterCriticalSection(&protseq
->cs
);
1563 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_tcp
, common
);
1565 if (poll_info
[i
].fd
== conn
->sock
) break;
1566 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_tcp
, common
);
1570 RPCRT4_SpawnConnection(&cconn
, &conn
->common
);
1572 ERR("failed to locate connection for fd %d\n", poll_info
[i
].fd
);
1573 LeaveCriticalSection(&protseq
->cs
);
1575 RPCRT4_new_client(cconn
);
1583 #else /* HAVE_SOCKETPAIR */
1585 typedef struct _RpcServerProtseq_sock
1587 RpcServerProtseq common
;
1589 } RpcServerProtseq_sock
;
1591 static RpcServerProtseq
*rpcrt4_protseq_sock_alloc(void)
1593 RpcServerProtseq_sock
*ps
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ps
));
1596 static BOOL wsa_inited
;
1600 WSAStartup(MAKEWORD(2, 2), &wsadata
);
1601 /* Note: WSAStartup can be called more than once so we don't bother with
1602 * making accesses to wsa_inited thread-safe */
1605 ps
->mgr_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1610 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq
*protseq
)
1612 RpcServerProtseq_sock
*sockps
= CONTAINING_RECORD(protseq
, RpcServerProtseq_sock
, common
);
1613 SetEvent(sockps
->mgr_event
);
1616 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq
*protseq
, void *prev_array
, unsigned int *count
)
1618 HANDLE
*objs
= prev_array
;
1619 RpcConnection_tcp
*conn
;
1620 RpcServerProtseq_sock
*sockps
= CONTAINING_RECORD(protseq
, RpcServerProtseq_sock
, common
);
1622 EnterCriticalSection(&protseq
->cs
);
1624 /* open and count connections */
1626 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_tcp
, common
);
1629 if (conn
->sock
!= -1)
1631 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_tcp
, common
);
1634 /* make array of connections */
1636 objs
= HeapReAlloc(GetProcessHeap(), 0, objs
, *count
*sizeof(HANDLE
));
1638 objs
= HeapAlloc(GetProcessHeap(), 0, *count
*sizeof(HANDLE
));
1641 ERR("couldn't allocate objs\n");
1642 LeaveCriticalSection(&protseq
->cs
);
1646 objs
[0] = sockps
->mgr_event
;
1648 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_tcp
, common
);
1651 if (conn
->sock
!= -1)
1653 int res
= WSAEventSelect(conn
->sock
, conn
->sock_event
, FD_ACCEPT
);
1654 if (res
== SOCKET_ERROR
)
1655 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1658 objs
[*count
] = conn
->sock_event
;
1662 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_tcp
, common
);
1664 LeaveCriticalSection(&protseq
->cs
);
1668 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq
*protseq
, void *array
)
1670 HeapFree(GetProcessHeap(), 0, array
);
1673 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq
*protseq
, unsigned int count
, void *wait_array
)
1676 HANDLE
*objs
= wait_array
;
1678 RpcConnection
*cconn
;
1679 RpcConnection_tcp
*conn
;
1686 /* an alertable wait isn't strictly necessary, but due to our
1687 * overlapped I/O implementation in Wine we need to free some memory
1688 * by the file user APC being called, even if no completion routine was
1689 * specified at the time of starting the async operation */
1690 res
= WaitForMultipleObjectsEx(count
, objs
, FALSE
, INFINITE
, TRUE
);
1691 } while (res
== WAIT_IO_COMPLETION
);
1693 if (res
== WAIT_OBJECT_0
)
1695 else if (res
== WAIT_FAILED
)
1697 ERR("wait failed with error %d\n", GetLastError());
1702 b_handle
= objs
[res
- WAIT_OBJECT_0
];
1703 /* find which connection got a RPC */
1704 EnterCriticalSection(&protseq
->cs
);
1705 conn
= CONTAINING_RECORD(protseq
->conn
, RpcConnection_tcp
, common
);
1708 if (b_handle
== conn
->sock_event
) break;
1709 conn
= CONTAINING_RECORD(conn
->common
.Next
, RpcConnection_tcp
, common
);
1713 RPCRT4_SpawnConnection(&cconn
, &conn
->common
);
1715 ERR("failed to locate connection for handle %p\n", b_handle
);
1716 LeaveCriticalSection(&protseq
->cs
);
1719 RPCRT4_new_client(cconn
);
1726 #endif /* HAVE_SOCKETPAIR */
1728 static RPC_STATUS
rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data
,
1733 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data
, tower_size
,
1734 networkaddr
, EPM_PROTOCOL_TCP
,
1738 static const struct connection_ops conn_protseq_list
[] = {
1740 { EPM_PROTOCOL_NCACN
, EPM_PROTOCOL_SMB
},
1741 rpcrt4_conn_np_alloc
,
1742 rpcrt4_ncacn_np_open
,
1743 rpcrt4_ncacn_np_handoff
,
1744 rpcrt4_conn_np_read
,
1745 rpcrt4_conn_np_write
,
1746 rpcrt4_conn_np_close
,
1747 rpcrt4_conn_np_cancel_call
,
1748 rpcrt4_conn_np_wait_for_incoming_data
,
1749 rpcrt4_ncacn_np_get_top_of_tower
,
1750 rpcrt4_ncacn_np_parse_top_of_tower
,
1753 { EPM_PROTOCOL_NCALRPC
, EPM_PROTOCOL_PIPE
},
1754 rpcrt4_conn_np_alloc
,
1755 rpcrt4_ncalrpc_open
,
1756 rpcrt4_ncalrpc_handoff
,
1757 rpcrt4_conn_np_read
,
1758 rpcrt4_conn_np_write
,
1759 rpcrt4_conn_np_close
,
1760 rpcrt4_conn_np_cancel_call
,
1761 rpcrt4_conn_np_wait_for_incoming_data
,
1762 rpcrt4_ncalrpc_get_top_of_tower
,
1763 rpcrt4_ncalrpc_parse_top_of_tower
,
1766 { EPM_PROTOCOL_NCACN
, EPM_PROTOCOL_TCP
},
1767 rpcrt4_conn_tcp_alloc
,
1768 rpcrt4_ncacn_ip_tcp_open
,
1769 rpcrt4_conn_tcp_handoff
,
1770 rpcrt4_conn_tcp_read
,
1771 rpcrt4_conn_tcp_write
,
1772 rpcrt4_conn_tcp_close
,
1773 rpcrt4_conn_tcp_cancel_call
,
1774 rpcrt4_conn_tcp_wait_for_incoming_data
,
1775 rpcrt4_ncacn_ip_tcp_get_top_of_tower
,
1776 rpcrt4_ncacn_ip_tcp_parse_top_of_tower
,
1782 static const struct protseq_ops protseq_list
[] =
1786 rpcrt4_protseq_np_alloc
,
1787 rpcrt4_protseq_np_signal_state_changed
,
1788 rpcrt4_protseq_np_get_wait_array
,
1789 rpcrt4_protseq_np_free_wait_array
,
1790 rpcrt4_protseq_np_wait_for_new_connection
,
1791 rpcrt4_protseq_ncacn_np_open_endpoint
,
1795 rpcrt4_protseq_np_alloc
,
1796 rpcrt4_protseq_np_signal_state_changed
,
1797 rpcrt4_protseq_np_get_wait_array
,
1798 rpcrt4_protseq_np_free_wait_array
,
1799 rpcrt4_protseq_np_wait_for_new_connection
,
1800 rpcrt4_protseq_ncalrpc_open_endpoint
,
1804 rpcrt4_protseq_sock_alloc
,
1805 rpcrt4_protseq_sock_signal_state_changed
,
1806 rpcrt4_protseq_sock_get_wait_array
,
1807 rpcrt4_protseq_sock_free_wait_array
,
1808 rpcrt4_protseq_sock_wait_for_new_connection
,
1809 rpcrt4_protseq_ncacn_ip_tcp_open_endpoint
,
1813 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
1815 const struct protseq_ops
*rpcrt4_get_protseq_ops(const char *protseq
)
1818 for(i
=0; i
<ARRAYSIZE(protseq_list
); i
++)
1819 if (!strcmp(protseq_list
[i
].name
, protseq
))
1820 return &protseq_list
[i
];
1824 static const struct connection_ops
*rpcrt4_get_conn_protseq_ops(const char *protseq
)
1827 for(i
=0; i
<ARRAYSIZE(conn_protseq_list
); i
++)
1828 if (!strcmp(conn_protseq_list
[i
].name
, protseq
))
1829 return &conn_protseq_list
[i
];
1833 /**** interface to rest of code ****/
1835 RPC_STATUS
RPCRT4_OpenClientConnection(RpcConnection
* Connection
)
1837 TRACE("(Connection == ^%p)\n", Connection
);
1839 assert(!Connection
->server
);
1840 return Connection
->ops
->open_connection_client(Connection
);
1843 RPC_STATUS
RPCRT4_CloseConnection(RpcConnection
* Connection
)
1845 TRACE("(Connection == ^%p)\n", Connection
);
1846 if (SecIsValidHandle(&Connection
->ctx
))
1848 DeleteSecurityContext(&Connection
->ctx
);
1849 SecInvalidateHandle(&Connection
->ctx
);
1851 rpcrt4_conn_close(Connection
);
1855 RPC_STATUS
RPCRT4_CreateConnection(RpcConnection
** Connection
, BOOL server
,
1856 LPCSTR Protseq
, LPCSTR NetworkAddr
, LPCSTR Endpoint
,
1857 LPCWSTR NetworkOptions
, RpcAuthInfo
* AuthInfo
, RpcQualityOfService
*QOS
)
1859 const struct connection_ops
*ops
;
1860 RpcConnection
* NewConnection
;
1862 ops
= rpcrt4_get_conn_protseq_ops(Protseq
);
1865 FIXME("not supported for protseq %s\n", Protseq
);
1866 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
1869 NewConnection
= ops
->alloc();
1870 NewConnection
->Next
= NULL
;
1871 NewConnection
->server_binding
= NULL
;
1872 NewConnection
->server
= server
;
1873 NewConnection
->ops
= ops
;
1874 NewConnection
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
1875 NewConnection
->Endpoint
= RPCRT4_strdupA(Endpoint
);
1876 NewConnection
->NetworkOptions
= RPCRT4_strdupW(NetworkOptions
);
1877 NewConnection
->MaxTransmissionSize
= RPC_MAX_PACKET_SIZE
;
1878 memset(&NewConnection
->ActiveInterface
, 0, sizeof(NewConnection
->ActiveInterface
));
1879 NewConnection
->NextCallId
= 1;
1881 SecInvalidateHandle(&NewConnection
->ctx
);
1882 memset(&NewConnection
->exp
, 0, sizeof(NewConnection
->exp
));
1883 NewConnection
->attr
= 0;
1884 if (AuthInfo
) RpcAuthInfo_AddRef(AuthInfo
);
1885 NewConnection
->AuthInfo
= AuthInfo
;
1886 NewConnection
->encryption_auth_len
= 0;
1887 NewConnection
->signature_auth_len
= 0;
1888 if (QOS
) RpcQualityOfService_AddRef(QOS
);
1889 NewConnection
->QOS
= QOS
;
1891 list_init(&NewConnection
->conn_pool_entry
);
1892 NewConnection
->async_state
= NULL
;
1894 TRACE("connection: %p\n", NewConnection
);
1895 *Connection
= NewConnection
;
1900 static RPC_STATUS
RPCRT4_SpawnConnection(RpcConnection
** Connection
, RpcConnection
* OldConnection
)
1904 err
= RPCRT4_CreateConnection(Connection
, OldConnection
->server
,
1905 rpcrt4_conn_get_name(OldConnection
),
1906 OldConnection
->NetworkAddr
,
1907 OldConnection
->Endpoint
, NULL
,
1908 OldConnection
->AuthInfo
, OldConnection
->QOS
);
1909 if (err
== RPC_S_OK
)
1910 rpcrt4_conn_handoff(OldConnection
, *Connection
);
1914 RPC_STATUS
RPCRT4_DestroyConnection(RpcConnection
* Connection
)
1916 TRACE("connection: %p\n", Connection
);
1918 RPCRT4_CloseConnection(Connection
);
1919 RPCRT4_strfree(Connection
->Endpoint
);
1920 RPCRT4_strfree(Connection
->NetworkAddr
);
1921 HeapFree(GetProcessHeap(), 0, Connection
->NetworkOptions
);
1922 if (Connection
->AuthInfo
) RpcAuthInfo_Release(Connection
->AuthInfo
);
1923 if (Connection
->QOS
) RpcQualityOfService_Release(Connection
->QOS
);
1926 if (Connection
->server_binding
) RPCRT4_ReleaseBinding(Connection
->server_binding
);
1928 HeapFree(GetProcessHeap(), 0, Connection
);
1932 RPC_STATUS
RpcTransport_GetTopOfTower(unsigned char *tower_data
,
1934 const char *protseq
,
1935 const char *networkaddr
,
1936 const char *endpoint
)
1938 twr_empty_floor_t
*protocol_floor
;
1939 const struct connection_ops
*protseq_ops
= rpcrt4_get_conn_protseq_ops(protseq
);
1944 return RPC_S_INVALID_RPC_PROTSEQ
;
1948 *tower_size
= sizeof(*protocol_floor
);
1949 *tower_size
+= protseq_ops
->get_top_of_tower(NULL
, networkaddr
, endpoint
);
1953 protocol_floor
= (twr_empty_floor_t
*)tower_data
;
1954 protocol_floor
->count_lhs
= sizeof(protocol_floor
->protid
);
1955 protocol_floor
->protid
= protseq_ops
->epm_protocols
[0];
1956 protocol_floor
->count_rhs
= 0;
1958 tower_data
+= sizeof(*protocol_floor
);
1960 *tower_size
= protseq_ops
->get_top_of_tower(tower_data
, networkaddr
, endpoint
);
1962 return EPT_S_NOT_REGISTERED
;
1964 *tower_size
+= sizeof(*protocol_floor
);
1969 RPC_STATUS
RpcTransport_ParseTopOfTower(const unsigned char *tower_data
,
1975 const twr_empty_floor_t
*protocol_floor
;
1976 const twr_empty_floor_t
*floor4
;
1977 const struct connection_ops
*protseq_ops
= NULL
;
1981 if (tower_size
< sizeof(*protocol_floor
))
1982 return EPT_S_NOT_REGISTERED
;
1984 protocol_floor
= (const twr_empty_floor_t
*)tower_data
;
1985 tower_data
+= sizeof(*protocol_floor
);
1986 tower_size
-= sizeof(*protocol_floor
);
1987 if ((protocol_floor
->count_lhs
!= sizeof(protocol_floor
->protid
)) ||
1988 (protocol_floor
->count_rhs
> tower_size
))
1989 return EPT_S_NOT_REGISTERED
;
1990 tower_data
+= protocol_floor
->count_rhs
;
1991 tower_size
-= protocol_floor
->count_rhs
;
1993 floor4
= (const twr_empty_floor_t
*)tower_data
;
1994 if ((tower_size
< sizeof(*floor4
)) ||
1995 (floor4
->count_lhs
!= sizeof(floor4
->protid
)))
1996 return EPT_S_NOT_REGISTERED
;
1998 for(i
= 0; i
< ARRAYSIZE(conn_protseq_list
); i
++)
1999 if ((protocol_floor
->protid
== conn_protseq_list
[i
].epm_protocols
[0]) &&
2000 (floor4
->protid
== conn_protseq_list
[i
].epm_protocols
[1]))
2002 protseq_ops
= &conn_protseq_list
[i
];
2007 return EPT_S_NOT_REGISTERED
;
2009 status
= protseq_ops
->parse_top_of_tower(tower_data
, tower_size
, networkaddr
, endpoint
);
2011 if ((status
== RPC_S_OK
) && protseq
)
2013 *protseq
= I_RpcAllocate(strlen(protseq_ops
->name
) + 1);
2014 strcpy(*protseq
, protseq_ops
->name
);
2020 /***********************************************************************
2021 * RpcNetworkIsProtseqValidW (RPCRT4.@)
2023 * Checks if the given protocol sequence is known by the RPC system.
2024 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
2027 RPC_STATUS WINAPI
RpcNetworkIsProtseqValidW(RPC_WSTR protseq
)
2031 WideCharToMultiByte(CP_ACP
, 0, protseq
, -1,
2032 ps
, sizeof ps
, NULL
, NULL
);
2033 if (rpcrt4_get_conn_protseq_ops(ps
))
2036 FIXME("Unknown protseq %s\n", debugstr_w(protseq
));
2038 return RPC_S_INVALID_RPC_PROTSEQ
;
2041 /***********************************************************************
2042 * RpcNetworkIsProtseqValidA (RPCRT4.@)
2044 RPC_STATUS WINAPI
RpcNetworkIsProtseqValidA(RPC_CSTR protseq
)
2046 UNICODE_STRING protseqW
;
2048 if (RtlCreateUnicodeStringFromAsciiz(&protseqW
, (char*)protseq
))
2050 RPC_STATUS ret
= RpcNetworkIsProtseqValidW(protseqW
.Buffer
);
2051 RtlFreeUnicodeString(&protseqW
);
2054 return RPC_S_OUT_OF_MEMORY
;