Assorted spelling fixes.
[wine] / dlls / rpcrt4 / rpc_transport.c
1 /*
2  * RPC transport layer
3  *
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
9  *
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.
14  *
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.
19  *
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
23  *
24  */
25
26 #include "config.h"
27
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <sys/types.h>
34
35 #if defined(__MINGW32__) || defined (_MSC_VER)
36 # include <ws2tcpip.h>
37 # ifndef EADDRINUSE
38 #  define EADDRINUSE WSAEADDRINUSE
39 # endif
40 # ifndef EAGAIN
41 #  define EAGAIN WSAEWOULDBLOCK
42 # endif
43 #else
44 # include <errno.h>
45 # ifdef HAVE_UNISTD_H
46 #  include <unistd.h>
47 # endif
48 # include <fcntl.h>
49 # ifdef HAVE_SYS_SOCKET_H
50 #  include <sys/socket.h>
51 # endif
52 # ifdef HAVE_NETINET_IN_H
53 #  include <netinet/in.h>
54 # endif
55 # ifdef HAVE_NETINET_TCP_H
56 #  include <netinet/tcp.h>
57 # endif
58 # ifdef HAVE_ARPA_INET_H
59 #  include <arpa/inet.h>
60 # endif
61 # ifdef HAVE_NETDB_H
62 #  include <netdb.h>
63 # endif
64 # ifdef HAVE_SYS_POLL_H
65 #  include <sys/poll.h>
66 # endif
67 # define closesocket close
68 #endif /* defined(__MINGW32__) || defined (_MSC_VER) */
69
70 #include "windef.h"
71 #include "winbase.h"
72 #include "winnls.h"
73 #include "winerror.h"
74 #include "winternl.h"
75 #include "wine/unicode.h"
76
77 #include "rpc.h"
78 #include "rpcndr.h"
79
80 #include "wine/debug.h"
81
82 #include "rpc_binding.h"
83 #include "rpc_message.h"
84 #include "rpc_server.h"
85 #include "epm_towers.h"
86
87 #ifndef SOL_TCP
88 # define SOL_TCP IPPROTO_TCP
89 #endif
90
91 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
92
93 /**** ncacn_np support ****/
94
95 typedef struct _RpcConnection_np
96 {
97   RpcConnection common;
98   HANDLE pipe;
99   OVERLAPPED ovl;
100   BOOL listening;
101 } RpcConnection_np;
102
103 static RpcConnection *rpcrt4_conn_np_alloc(void)
104 {
105   RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np));
106   if (npc)
107   {
108     npc->pipe = NULL;
109     memset(&npc->ovl, 0, sizeof(npc->ovl));
110     npc->listening = FALSE;
111   }
112   return &npc->common;
113 }
114
115 static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
116 {
117   if (npc->listening)
118     return RPC_S_OK;
119
120   npc->listening = TRUE;
121   for (;;)
122   {
123       if (ConnectNamedPipe(npc->pipe, &npc->ovl))
124           return RPC_S_OK;
125
126       switch(GetLastError())
127       {
128       case ERROR_PIPE_CONNECTED:
129           SetEvent(npc->ovl.hEvent);
130           return RPC_S_OK;
131       case ERROR_IO_PENDING:
132           /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */
133           return RPC_S_OK;
134       case ERROR_NO_DATA_DETECTED:
135           /* client has disconnected, retry */
136           DisconnectNamedPipe( npc->pipe );
137           break;
138       default:
139           npc->listening = FALSE;
140           WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());
141           return RPC_S_OUT_OF_RESOURCES;
142       }
143   }
144 }
145
146 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
147 {
148   RpcConnection_np *npc = (RpcConnection_np *) Connection;
149   TRACE("listening on %s\n", pname);
150
151   npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX,
152                                PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
153                                PIPE_UNLIMITED_INSTANCES,
154                                RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
155   if (npc->pipe == INVALID_HANDLE_VALUE) {
156     WARN("CreateNamedPipe failed with error %d\n", GetLastError());
157     if (GetLastError() == ERROR_FILE_EXISTS)
158       return RPC_S_DUPLICATE_ENDPOINT;
159     else
160       return RPC_S_CANT_CREATE_ENDPOINT;
161   }
162
163   memset(&npc->ovl, 0, sizeof(npc->ovl));
164   npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
165
166   /* Note: we don't call ConnectNamedPipe here because it must be done in the
167    * server thread as the thread must be alertable */
168   return RPC_S_OK;
169 }
170
171 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait)
172 {
173   RpcConnection_np *npc = (RpcConnection_np *) Connection;
174   HANDLE pipe;
175   DWORD err, dwMode;
176
177   TRACE("connecting to %s\n", pname);
178
179   while (TRUE) {
180     DWORD dwFlags = 0;
181     if (Connection->QOS)
182     {
183         dwFlags = SECURITY_SQOS_PRESENT;
184         switch (Connection->QOS->qos->ImpersonationType)
185         {
186             case RPC_C_IMP_LEVEL_DEFAULT:
187                 /* FIXME: what to do here? */
188                 break;
189             case RPC_C_IMP_LEVEL_ANONYMOUS:
190                 dwFlags |= SECURITY_ANONYMOUS;
191                 break;
192             case RPC_C_IMP_LEVEL_IDENTIFY:
193                 dwFlags |= SECURITY_IDENTIFICATION;
194                 break;
195             case RPC_C_IMP_LEVEL_IMPERSONATE:
196                 dwFlags |= SECURITY_IMPERSONATION;
197                 break;
198             case RPC_C_IMP_LEVEL_DELEGATE:
199                 dwFlags |= SECURITY_DELEGATION;
200                 break;
201         }
202         if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTIFY_DYNAMIC)
203             dwFlags |= SECURITY_CONTEXT_TRACKING;
204     }
205     pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
206                        OPEN_EXISTING, dwFlags, 0);
207     if (pipe != INVALID_HANDLE_VALUE) break;
208     err = GetLastError();
209     if (err == ERROR_PIPE_BUSY) {
210       TRACE("connection failed, error=%x\n", err);
211       return RPC_S_SERVER_TOO_BUSY;
212     }
213     if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
214       err = GetLastError();
215       WARN("connection failed, error=%x\n", err);
216       return RPC_S_SERVER_UNAVAILABLE;
217     }
218   }
219
220   /* success */
221   memset(&npc->ovl, 0, sizeof(npc->ovl));
222   /* pipe is connected; change to message-read mode. */
223   dwMode = PIPE_READMODE_MESSAGE;
224   SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
225   npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
226   npc->pipe = pipe;
227
228   return RPC_S_OK;
229 }
230
231 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection)
232 {
233   RpcConnection_np *npc = (RpcConnection_np *) Connection;
234   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
235   RPC_STATUS r;
236   LPSTR pname;
237
238   /* already connected? */
239   if (npc->pipe)
240     return RPC_S_OK;
241
242   /* protseq=ncalrpc: supposed to use NT LPC ports,
243    * but we'll implement it with named pipes for now */
244   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
245   strcat(strcpy(pname, prefix), Connection->Endpoint);
246   r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
247   I_RpcFree(pname);
248
249   return r;
250 }
251
252 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint)
253 {
254   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
255   RPC_STATUS r;
256   LPSTR pname;
257   RpcConnection *Connection;
258
259   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
260                               endpoint, NULL, NULL, NULL);
261   if (r != RPC_S_OK)
262       return r;
263
264   /* protseq=ncalrpc: supposed to use NT LPC ports,
265    * but we'll implement it with named pipes for now */
266   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
267   strcat(strcpy(pname, prefix), Connection->Endpoint);
268   r = rpcrt4_conn_create_pipe(Connection, pname);
269   I_RpcFree(pname);
270
271   EnterCriticalSection(&protseq->cs);
272   Connection->Next = protseq->conn;
273   protseq->conn = Connection;
274   LeaveCriticalSection(&protseq->cs);
275
276   return r;
277 }
278
279 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
280 {
281   RpcConnection_np *npc = (RpcConnection_np *) Connection;
282   static const char prefix[] = "\\\\.";
283   RPC_STATUS r;
284   LPSTR pname;
285
286   /* already connected? */
287   if (npc->pipe)
288     return RPC_S_OK;
289
290   /* protseq=ncacn_np: named pipes */
291   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
292   strcat(strcpy(pname, prefix), Connection->Endpoint);
293   r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
294   I_RpcFree(pname);
295
296   return r;
297 }
298
299 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
300 {
301   static const char prefix[] = "\\\\.";
302   RPC_STATUS r;
303   LPSTR pname;
304   RpcConnection *Connection;
305
306   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
307                               endpoint, NULL, NULL, NULL);
308   if (r != RPC_S_OK)
309     return r;
310
311   /* protseq=ncacn_np: named pipes */
312   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
313   strcat(strcpy(pname, prefix), Connection->Endpoint);
314   r = rpcrt4_conn_create_pipe(Connection, pname);
315   I_RpcFree(pname);
316
317   EnterCriticalSection(&protseq->cs);
318   Connection->Next = protseq->conn;
319   protseq->conn = Connection;
320   LeaveCriticalSection(&protseq->cs);
321
322   return r;
323 }
324
325 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc)
326 {    
327   /* because of the way named pipes work, we'll transfer the connected pipe
328    * to the child, then reopen the server binding to continue listening */
329
330   new_npc->pipe = old_npc->pipe;
331   new_npc->ovl = old_npc->ovl;
332   old_npc->pipe = 0;
333   memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));
334   old_npc->listening = FALSE;
335 }
336
337 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
338 {
339   RPC_STATUS status;
340   LPSTR pname;
341   static const char prefix[] = "\\\\.";
342
343   rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
344
345   pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
346   strcat(strcpy(pname, prefix), old_conn->Endpoint);
347   status = rpcrt4_conn_create_pipe(old_conn, pname);
348   I_RpcFree(pname);
349
350   return status;
351 }
352
353 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
354 {
355   RPC_STATUS status;
356   LPSTR pname;
357   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
358
359   TRACE("%s\n", old_conn->Endpoint);
360
361   rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
362
363   pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
364   strcat(strcpy(pname, prefix), old_conn->Endpoint);
365   status = rpcrt4_conn_create_pipe(old_conn, pname);
366   I_RpcFree(pname);
367     
368   return status;
369 }
370
371 static int rpcrt4_conn_np_read(RpcConnection *Connection,
372                         void *buffer, unsigned int count)
373 {
374   RpcConnection_np *npc = (RpcConnection_np *) Connection;
375   char *buf = buffer;
376   BOOL ret = TRUE;
377   unsigned int bytes_left = count;
378
379   while (bytes_left)
380   {
381     DWORD bytes_read;
382     ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, NULL);
383     if (!ret || !bytes_read)
384         break;
385     bytes_left -= bytes_read;
386     buf += bytes_read;
387   }
388   return ret ? count : -1;
389 }
390
391 static int rpcrt4_conn_np_write(RpcConnection *Connection,
392                              const void *buffer, unsigned int count)
393 {
394   RpcConnection_np *npc = (RpcConnection_np *) Connection;
395   const char *buf = buffer;
396   BOOL ret = TRUE;
397   unsigned int bytes_left = count;
398
399   while (bytes_left)
400   {
401     DWORD bytes_written;
402     ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, NULL);
403     if (!ret || !bytes_written)
404         break;
405     bytes_left -= bytes_written;
406     buf += bytes_written;
407   }
408   return ret ? count : -1;
409 }
410
411 static int rpcrt4_conn_np_close(RpcConnection *Connection)
412 {
413   RpcConnection_np *npc = (RpcConnection_np *) Connection;
414   if (npc->pipe) {
415     FlushFileBuffers(npc->pipe);
416     CloseHandle(npc->pipe);
417     npc->pipe = 0;
418   }
419   if (npc->ovl.hEvent) {
420     CloseHandle(npc->ovl.hEvent);
421     npc->ovl.hEvent = 0;
422   }
423   return 0;
424 }
425
426 static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection)
427 {
428     /* FIXME: implement when named pipe writes use overlapped I/O */
429 }
430
431 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection)
432 {
433     /* FIXME: implement when named pipe writes use overlapped I/O */
434     return -1;
435 }
436
437 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
438                                                const char *networkaddr,
439                                                const char *endpoint)
440 {
441     twr_empty_floor_t *smb_floor;
442     twr_empty_floor_t *nb_floor;
443     size_t size;
444     size_t networkaddr_size;
445     size_t endpoint_size;
446
447     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
448
449     networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
450     endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
451     size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
452
453     if (!tower_data)
454         return size;
455
456     smb_floor = (twr_empty_floor_t *)tower_data;
457
458     tower_data += sizeof(*smb_floor);
459
460     smb_floor->count_lhs = sizeof(smb_floor->protid);
461     smb_floor->protid = EPM_PROTOCOL_SMB;
462     smb_floor->count_rhs = endpoint_size;
463
464     if (endpoint)
465         memcpy(tower_data, endpoint, endpoint_size);
466     else
467         tower_data[0] = 0;
468     tower_data += endpoint_size;
469
470     nb_floor = (twr_empty_floor_t *)tower_data;
471
472     tower_data += sizeof(*nb_floor);
473
474     nb_floor->count_lhs = sizeof(nb_floor->protid);
475     nb_floor->protid = EPM_PROTOCOL_NETBIOS;
476     nb_floor->count_rhs = networkaddr_size;
477
478     if (networkaddr)
479         memcpy(tower_data, networkaddr, networkaddr_size);
480     else
481         tower_data[0] = 0;
482
483     return size;
484 }
485
486 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
487                                                      size_t tower_size,
488                                                      char **networkaddr,
489                                                      char **endpoint)
490 {
491     const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
492     const twr_empty_floor_t *nb_floor;
493
494     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
495
496     if (tower_size < sizeof(*smb_floor))
497         return EPT_S_NOT_REGISTERED;
498
499     tower_data += sizeof(*smb_floor);
500     tower_size -= sizeof(*smb_floor);
501
502     if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
503         (smb_floor->protid != EPM_PROTOCOL_SMB) ||
504         (smb_floor->count_rhs > tower_size) ||
505         (tower_data[smb_floor->count_rhs - 1] != '\0'))
506         return EPT_S_NOT_REGISTERED;
507
508     if (endpoint)
509     {
510         *endpoint = I_RpcAllocate(smb_floor->count_rhs);
511         if (!*endpoint)
512             return RPC_S_OUT_OF_RESOURCES;
513         memcpy(*endpoint, tower_data, smb_floor->count_rhs);
514     }
515     tower_data += smb_floor->count_rhs;
516     tower_size -= smb_floor->count_rhs;
517
518     if (tower_size < sizeof(*nb_floor))
519         return EPT_S_NOT_REGISTERED;
520
521     nb_floor = (const twr_empty_floor_t *)tower_data;
522
523     tower_data += sizeof(*nb_floor);
524     tower_size -= sizeof(*nb_floor);
525
526     if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
527         (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
528         (nb_floor->count_rhs > tower_size) ||
529         (tower_data[nb_floor->count_rhs - 1] != '\0'))
530         return EPT_S_NOT_REGISTERED;
531
532     if (networkaddr)
533     {
534         *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
535         if (!*networkaddr)
536         {
537             if (endpoint)
538             {
539                 I_RpcFree(*endpoint);
540                 *endpoint = NULL;
541             }
542             return RPC_S_OUT_OF_RESOURCES;
543         }
544         memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
545     }
546
547     return RPC_S_OK;
548 }
549
550 typedef struct _RpcServerProtseq_np
551 {
552     RpcServerProtseq common;
553     HANDLE mgr_event;
554 } RpcServerProtseq_np;
555
556 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void)
557 {
558     RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
559     if (ps)
560         ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
561     return &ps->common;
562 }
563
564 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
565 {
566     RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
567     SetEvent(npps->mgr_event);
568 }
569
570 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
571 {
572     HANDLE *objs = prev_array;
573     RpcConnection_np *conn;
574     RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
575     
576     EnterCriticalSection(&protseq->cs);
577     
578     /* open and count connections */
579     *count = 1;
580     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
581     while (conn) {
582         rpcrt4_conn_listen_pipe(conn);
583         if (conn->ovl.hEvent)
584             (*count)++;
585         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
586     }
587     
588     /* make array of connections */
589     if (objs)
590         objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
591     else
592         objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
593     if (!objs)
594     {
595         ERR("couldn't allocate objs\n");
596         LeaveCriticalSection(&protseq->cs);
597         return NULL;
598     }
599     
600     objs[0] = npps->mgr_event;
601     *count = 1;
602     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
603     while (conn) {
604         if ((objs[*count] = conn->ovl.hEvent))
605             (*count)++;
606         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
607     }
608     LeaveCriticalSection(&protseq->cs);
609     return objs;
610 }
611
612 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array)
613 {
614     HeapFree(GetProcessHeap(), 0, array);
615 }
616
617 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
618 {
619     HANDLE b_handle;
620     HANDLE *objs = wait_array;
621     DWORD res;
622     RpcConnection *cconn;
623     RpcConnection_np *conn;
624     
625     if (!objs)
626         return -1;
627
628     do
629     {
630         /* an alertable wait isn't strictly necessary, but due to our
631          * overlapped I/O implementation in Wine we need to free some memory
632          * by the file user APC being called, even if no completion routine was
633          * specified at the time of starting the async operation */
634         res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
635     } while (res == WAIT_IO_COMPLETION);
636
637     if (res == WAIT_OBJECT_0)
638         return 0;
639     else if (res == WAIT_FAILED)
640     {
641         ERR("wait failed with error %d\n", GetLastError());
642         return -1;
643     }
644     else
645     {
646         b_handle = objs[res - WAIT_OBJECT_0];
647         /* find which connection got a RPC */
648         EnterCriticalSection(&protseq->cs);
649         conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
650         while (conn) {
651             if (b_handle == conn->ovl.hEvent) break;
652             conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
653         }
654         cconn = NULL;
655         if (conn)
656             RPCRT4_SpawnConnection(&cconn, &conn->common);
657         else
658             ERR("failed to locate connection for handle %p\n", b_handle);
659         LeaveCriticalSection(&protseq->cs);
660         if (cconn)
661         {
662             RPCRT4_new_client(cconn);
663             return 1;
664         }
665         else return -1;
666     }
667 }
668
669 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
670                                               const char *networkaddr,
671                                               const char *endpoint)
672 {
673     twr_empty_floor_t *pipe_floor;
674     size_t size;
675     size_t endpoint_size;
676
677     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
678
679     endpoint_size = strlen(endpoint) + 1;
680     size = sizeof(*pipe_floor) + endpoint_size;
681
682     if (!tower_data)
683         return size;
684
685     pipe_floor = (twr_empty_floor_t *)tower_data;
686
687     tower_data += sizeof(*pipe_floor);
688
689     pipe_floor->count_lhs = sizeof(pipe_floor->protid);
690     pipe_floor->protid = EPM_PROTOCOL_PIPE;
691     pipe_floor->count_rhs = endpoint_size;
692
693     memcpy(tower_data, endpoint, endpoint_size);
694
695     return size;
696 }
697
698 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
699                                                     size_t tower_size,
700                                                     char **networkaddr,
701                                                     char **endpoint)
702 {
703     const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
704
705     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
706
707     if (tower_size < sizeof(*pipe_floor))
708         return EPT_S_NOT_REGISTERED;
709
710     tower_data += sizeof(*pipe_floor);
711     tower_size -= sizeof(*pipe_floor);
712
713     if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
714         (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
715         (pipe_floor->count_rhs > tower_size) ||
716         (tower_data[pipe_floor->count_rhs - 1] != '\0'))
717         return EPT_S_NOT_REGISTERED;
718
719     if (networkaddr)
720         *networkaddr = NULL;
721
722     if (endpoint)
723     {
724         *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
725         if (!*endpoint)
726             return RPC_S_OUT_OF_RESOURCES;
727         memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
728     }
729
730     return RPC_S_OK;
731 }
732
733 /**** ncacn_ip_tcp support ****/
734
735 #ifdef HAVE_SOCKETPAIR
736
737 typedef struct _RpcConnection_tcp
738 {
739   RpcConnection common;
740   int sock;
741   int cancel_fds[2];
742 } RpcConnection_tcp;
743
744 static RpcConnection *rpcrt4_conn_tcp_alloc(void)
745 {
746   RpcConnection_tcp *tcpc;
747   tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp));
748   if (tcpc == NULL)
749     return NULL;
750   tcpc->sock = -1;
751   if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
752   {
753     ERR("socketpair() failed: %s\n", strerror(errno));
754     HeapFree(GetProcessHeap(), 0, tcpc);
755     return NULL;
756   }
757   return &tcpc->common;
758 }
759
760 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
761 {
762   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
763   int sock;
764   int ret;
765   struct addrinfo *ai;
766   struct addrinfo *ai_cur;
767   struct addrinfo hints;
768
769   TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
770
771   if (tcpc->sock != -1)
772     return RPC_S_OK;
773
774   hints.ai_flags          = 0;
775   hints.ai_family         = PF_UNSPEC;
776   hints.ai_socktype       = SOCK_STREAM;
777   hints.ai_protocol       = IPPROTO_TCP;
778   hints.ai_addrlen        = 0;
779   hints.ai_addr           = NULL;
780   hints.ai_canonname      = NULL;
781   hints.ai_next           = NULL;
782
783   ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
784   if (ret)
785   {
786     ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
787       Connection->Endpoint, gai_strerror(ret));
788     return RPC_S_SERVER_UNAVAILABLE;
789   }
790
791   for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
792   {
793     int val;
794
795     if (TRACE_ON(rpc))
796     {
797       char host[256];
798       char service[256];
799       getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
800         host, sizeof(host), service, sizeof(service),
801         NI_NUMERICHOST | NI_NUMERICSERV);
802       TRACE("trying %s:%s\n", host, service);
803     }
804
805     sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
806     if (sock == -1)
807     {
808       WARN("socket() failed: %s\n", strerror(errno));
809       continue;
810     }
811
812     if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
813     {
814       WARN("connect() failed: %s\n", strerror(errno));
815       closesocket(sock);
816       continue;
817     }
818
819     /* RPC depends on having minimal latency so disable the Nagle algorithm */
820     val = 1;
821     setsockopt(sock, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
822     fcntl(sock, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
823
824     tcpc->sock = sock;
825
826     freeaddrinfo(ai);
827     TRACE("connected\n");
828     return RPC_S_OK;
829   }
830
831   freeaddrinfo(ai);
832   ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
833   return RPC_S_SERVER_UNAVAILABLE;
834 }
835
836 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
837 {
838     RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
839     int sock;
840     int ret;
841     struct addrinfo *ai;
842     struct addrinfo *ai_cur;
843     struct addrinfo hints;
844     RpcConnection *first_connection = NULL;
845
846     TRACE("(%p, %s)\n", protseq, endpoint);
847
848     hints.ai_flags          = AI_PASSIVE /* for non-localhost addresses */;
849     hints.ai_family         = PF_UNSPEC;
850     hints.ai_socktype       = SOCK_STREAM;
851     hints.ai_protocol       = IPPROTO_TCP;
852     hints.ai_addrlen        = 0;
853     hints.ai_addr           = NULL;
854     hints.ai_canonname      = NULL;
855     hints.ai_next           = NULL;
856
857     ret = getaddrinfo(NULL, endpoint, &hints, &ai);
858     if (ret)
859     {
860         ERR("getaddrinfo for port %s failed: %s\n", endpoint,
861             gai_strerror(ret));
862         if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
863             return RPC_S_INVALID_ENDPOINT_FORMAT;
864         return RPC_S_CANT_CREATE_ENDPOINT;
865     }
866
867     for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
868     {
869         RpcConnection_tcp *tcpc;
870         RPC_STATUS create_status;
871
872         if (TRACE_ON(rpc))
873         {
874             char host[256];
875             char service[256];
876             getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
877                         host, sizeof(host), service, sizeof(service),
878                         NI_NUMERICHOST | NI_NUMERICSERV);
879             TRACE("trying %s:%s\n", host, service);
880         }
881
882         sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
883         if (sock == -1)
884         {
885             WARN("socket() failed: %s\n", strerror(errno));
886             status = RPC_S_CANT_CREATE_ENDPOINT;
887             continue;
888         }
889
890         ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
891         if (ret < 0)
892         {
893             WARN("bind failed: %s\n", strerror(errno));
894             closesocket(sock);
895             if (errno == EADDRINUSE)
896               status = RPC_S_DUPLICATE_ENDPOINT;
897             else
898               status = RPC_S_CANT_CREATE_ENDPOINT;
899             continue;
900         }
901         create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
902                                                 protseq->Protseq, NULL,
903                                                 endpoint, NULL, NULL, NULL);
904         if (create_status != RPC_S_OK)
905         {
906             closesocket(sock);
907             status = create_status;
908             continue;
909         }
910
911         tcpc->sock = sock;
912         ret = listen(sock, protseq->MaxCalls);
913         if (ret < 0)
914         {
915             WARN("listen failed: %s\n", strerror(errno));
916             RPCRT4_DestroyConnection(&tcpc->common);
917             status = RPC_S_OUT_OF_RESOURCES;
918             continue;
919         }
920         /* need a non-blocking socket, otherwise accept() has a potential
921          * race-condition (poll() says it is readable, connection drops,
922          * and accept() blocks until the next connection comes...)
923          */
924         ret = fcntl(sock, F_SETFL, O_NONBLOCK);
925         if (ret < 0)
926         {
927             WARN("couldn't make socket non-blocking, error %d\n", ret);
928             RPCRT4_DestroyConnection(&tcpc->common);
929             status = RPC_S_OUT_OF_RESOURCES;
930             continue;
931         }
932
933         tcpc->common.Next = first_connection;
934         first_connection = &tcpc->common;
935     }
936
937     freeaddrinfo(ai);
938
939     /* if at least one connection was created for an endpoint then
940      * return success */
941     if (first_connection)
942     {
943         RpcConnection *conn;
944
945         /* find last element in list */
946         for (conn = first_connection; conn->Next; conn = conn->Next)
947             ;
948
949         EnterCriticalSection(&protseq->cs);
950         conn->Next = protseq->conn;
951         protseq->conn = first_connection;
952         LeaveCriticalSection(&protseq->cs);
953         
954         TRACE("listening on %s\n", endpoint);
955         return RPC_S_OK;
956     }
957
958     ERR("couldn't listen on port %s\n", endpoint);
959     return status;
960 }
961
962 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
963 {
964   int ret;
965   struct sockaddr_in address;
966   socklen_t addrsize;
967   RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;
968   RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;
969
970   addrsize = sizeof(address);
971   ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
972   if (ret < 0)
973   {
974     ERR("Failed to accept a TCP connection: error %d\n", ret);
975     return RPC_S_OUT_OF_RESOURCES;
976   }
977   /* reset to blocking behaviour */
978   fcntl(ret, F_SETFL, 0);
979   client->sock = ret;
980   TRACE("Accepted a new TCP connection\n");
981   return RPC_S_OK;
982 }
983
984 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
985                                 void *buffer, unsigned int count)
986 {
987   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
988   int bytes_read = 0;
989   do
990   {
991     int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
992     if (!r)
993       return -1;
994     else if (r > 0)
995       bytes_read += r;
996     else if (errno != EAGAIN)
997     {
998       WARN("recv() failed: %s\n", strerror(errno));
999       return -1;
1000     }
1001     else
1002     {
1003       struct pollfd pfds[2];
1004       pfds[0].fd = tcpc->sock;
1005       pfds[0].events = POLLIN;
1006       pfds[1].fd = tcpc->cancel_fds[0];
1007       pfds[1].events = POLLIN;
1008       if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1009       {
1010         ERR("poll() failed: %s\n", strerror(errno));
1011         return -1;
1012       }
1013       if (pfds[1].revents & POLLIN) /* canceled */
1014       {
1015         char dummy;
1016         read(pfds[1].fd, &dummy, sizeof(dummy));
1017         return -1;
1018       }
1019     }
1020   } while (bytes_read != count);
1021   TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1022   return bytes_read;
1023 }
1024
1025 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1026                                  const void *buffer, unsigned int count)
1027 {
1028   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1029   int bytes_written = 0;
1030   do
1031   {
1032     int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1033     if (r >= 0)
1034       bytes_written += r;
1035     else if (errno != EAGAIN)
1036       return -1;
1037     else
1038     {
1039       struct pollfd pfd;
1040       pfd.fd = tcpc->sock;
1041       pfd.events = POLLOUT;
1042       if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
1043       {
1044         ERR("poll() failed: %s\n", strerror(errno));
1045         return -1;
1046       }
1047     }
1048   } while (bytes_written != count);
1049   TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1050   return bytes_written;
1051 }
1052
1053 static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
1054 {
1055   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1056
1057   TRACE("%d\n", tcpc->sock);
1058
1059   if (tcpc->sock != -1)
1060     closesocket(tcpc->sock);
1061   tcpc->sock = -1;
1062   close(tcpc->cancel_fds[0]);
1063   close(tcpc->cancel_fds[1]);
1064   return 0;
1065 }
1066
1067 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
1068 {
1069     RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1070     char dummy = 1;
1071
1072     TRACE("%p\n", Connection);
1073
1074     write(tcpc->cancel_fds[1], &dummy, 1);
1075 }
1076
1077 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
1078 {
1079     RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1080     struct pollfd pfds[2];
1081
1082     TRACE("%p\n", Connection);
1083
1084     pfds[0].fd = tcpc->sock;
1085     pfds[0].events = POLLIN;
1086     pfds[1].fd = tcpc->cancel_fds[0];
1087     pfds[1].events = POLLIN;
1088     if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1089     {
1090       ERR("poll() failed: %s\n", strerror(errno));
1091       return -1;
1092     }
1093     if (pfds[1].revents & POLLIN) /* canceled */
1094     {
1095       char dummy;
1096       read(pfds[1].fd, &dummy, sizeof(dummy));
1097       return -1;
1098     }
1099
1100     return 0;
1101 }
1102
1103 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1104                                                    const char *networkaddr,
1105                                                    const char *endpoint)
1106 {
1107     twr_tcp_floor_t *tcp_floor;
1108     twr_ipv4_floor_t *ipv4_floor;
1109     struct addrinfo *ai;
1110     struct addrinfo hints;
1111     int ret;
1112     size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
1113
1114     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
1115
1116     if (!tower_data)
1117         return size;
1118
1119     tcp_floor = (twr_tcp_floor_t *)tower_data;
1120     tower_data += sizeof(*tcp_floor);
1121
1122     ipv4_floor = (twr_ipv4_floor_t *)tower_data;
1123
1124     tcp_floor->count_lhs = sizeof(tcp_floor->protid);
1125     tcp_floor->protid = EPM_PROTOCOL_TCP;
1126     tcp_floor->count_rhs = sizeof(tcp_floor->port);
1127
1128     ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
1129     ipv4_floor->protid = EPM_PROTOCOL_IP;
1130     ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
1131
1132     hints.ai_flags          = AI_NUMERICHOST;
1133     /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
1134     hints.ai_family         = PF_INET;
1135     hints.ai_socktype       = SOCK_STREAM;
1136     hints.ai_protocol       = IPPROTO_TCP;
1137     hints.ai_addrlen        = 0;
1138     hints.ai_addr           = NULL;
1139     hints.ai_canonname      = NULL;
1140     hints.ai_next           = NULL;
1141
1142     ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
1143     if (ret)
1144     {
1145         ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
1146         if (ret)
1147         {
1148             ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
1149             return 0;
1150         }
1151     }
1152
1153     if (ai->ai_family == PF_INET)
1154     {
1155         const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
1156         tcp_floor->port = sin->sin_port;
1157         ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
1158     }
1159     else
1160     {
1161         ERR("unexpected protocol family %d\n", ai->ai_family);
1162         return 0;
1163     }
1164
1165     freeaddrinfo(ai);
1166
1167     return size;
1168 }
1169
1170 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1171                                                          size_t tower_size,
1172                                                          char **networkaddr,
1173                                                          char **endpoint)
1174 {
1175     const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
1176     const twr_ipv4_floor_t *ipv4_floor;
1177     struct in_addr in_addr;
1178
1179     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
1180
1181     if (tower_size < sizeof(*tcp_floor))
1182         return EPT_S_NOT_REGISTERED;
1183
1184     tower_data += sizeof(*tcp_floor);
1185     tower_size -= sizeof(*tcp_floor);
1186
1187     if (tower_size < sizeof(*ipv4_floor))
1188         return EPT_S_NOT_REGISTERED;
1189
1190     ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
1191
1192     if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
1193         (tcp_floor->protid != EPM_PROTOCOL_TCP) ||
1194         (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
1195         (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
1196         (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
1197         (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
1198         return EPT_S_NOT_REGISTERED;
1199
1200     if (endpoint)
1201     {
1202         *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
1203         if (!*endpoint)
1204             return RPC_S_OUT_OF_RESOURCES;
1205         sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
1206     }
1207
1208     if (networkaddr)
1209     {
1210         *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
1211         if (!*networkaddr)
1212         {
1213             if (endpoint)
1214             {
1215                 I_RpcFree(*endpoint);
1216                 *endpoint = NULL;
1217             }
1218             return RPC_S_OUT_OF_RESOURCES;
1219         }
1220         in_addr.s_addr = ipv4_floor->ipv4addr;
1221         if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
1222         {
1223             ERR("inet_ntop: %s\n", strerror(errno));
1224             I_RpcFree(*networkaddr);
1225             *networkaddr = NULL;
1226             if (endpoint)
1227             {
1228                 I_RpcFree(*endpoint);
1229                 *endpoint = NULL;
1230             }
1231             return EPT_S_NOT_REGISTERED;
1232         }
1233     }
1234
1235     return RPC_S_OK;
1236 }
1237
1238 typedef struct _RpcServerProtseq_sock
1239 {
1240     RpcServerProtseq common;
1241     int mgr_event_rcv;
1242     int mgr_event_snd;
1243 } RpcServerProtseq_sock;
1244
1245 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1246 {
1247     RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1248     if (ps)
1249     {
1250         int fds[2];
1251         if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))
1252         {
1253             fcntl(fds[0], F_SETFL, O_NONBLOCK);
1254             fcntl(fds[1], F_SETFL, O_NONBLOCK);
1255             ps->mgr_event_rcv = fds[0];
1256             ps->mgr_event_snd = fds[1];
1257         }
1258         else
1259         {
1260             ERR("socketpair failed with error %s\n", strerror(errno));
1261             HeapFree(GetProcessHeap(), 0, ps);
1262             return NULL;
1263         }
1264     }
1265     return &ps->common;
1266 }
1267
1268 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1269 {
1270     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1271     char dummy = 1;
1272     write(sockps->mgr_event_snd, &dummy, sizeof(dummy));
1273 }
1274
1275 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1276 {
1277     struct pollfd *poll_info = prev_array;
1278     RpcConnection_tcp *conn;
1279     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1280
1281     EnterCriticalSection(&protseq->cs);
1282     
1283     /* open and count connections */
1284     *count = 1;
1285     conn = (RpcConnection_tcp *)protseq->conn;
1286     while (conn) {
1287         if (conn->sock != -1)
1288             (*count)++;
1289         conn = (RpcConnection_tcp *)conn->common.Next;
1290     }
1291     
1292     /* make array of connections */
1293     if (poll_info)
1294         poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));
1295     else
1296         poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));
1297     if (!poll_info)
1298     {
1299         ERR("couldn't allocate poll_info\n");
1300         LeaveCriticalSection(&protseq->cs);
1301         return NULL;
1302     }
1303
1304     poll_info[0].fd = sockps->mgr_event_rcv;
1305     poll_info[0].events = POLLIN;
1306     *count = 1;
1307     conn =  CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1308     while (conn) {
1309         if (conn->sock != -1)
1310         {
1311             poll_info[*count].fd = conn->sock;
1312             poll_info[*count].events = POLLIN;
1313             (*count)++;
1314         }
1315         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1316     }
1317     LeaveCriticalSection(&protseq->cs);
1318     return poll_info;
1319 }
1320
1321 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1322 {
1323     HeapFree(GetProcessHeap(), 0, array);
1324 }
1325
1326 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1327 {
1328     struct pollfd *poll_info = wait_array;
1329     int ret;
1330     unsigned int i;
1331     RpcConnection *cconn;
1332     RpcConnection_tcp *conn;
1333     
1334     if (!poll_info)
1335         return -1;
1336     
1337     ret = poll(poll_info, count, -1);
1338     if (ret < 0)
1339     {
1340         ERR("poll failed with error %d\n", ret);
1341         return -1;
1342     }
1343
1344     for (i = 0; i < count; i++)
1345         if (poll_info[i].revents & POLLIN)
1346         {
1347             /* RPC server event */
1348             if (i == 0)
1349             {
1350                 char dummy;
1351                 read(poll_info[0].fd, &dummy, sizeof(dummy));
1352                 return 0;
1353             }
1354
1355             /* find which connection got a RPC */
1356             EnterCriticalSection(&protseq->cs);
1357             conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1358             while (conn) {
1359                 if (poll_info[i].fd == conn->sock) break;
1360                 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1361             }
1362             cconn = NULL;
1363             if (conn)
1364                 RPCRT4_SpawnConnection(&cconn, &conn->common);
1365             else
1366                 ERR("failed to locate connection for fd %d\n", poll_info[i].fd);
1367             LeaveCriticalSection(&protseq->cs);
1368             if (cconn)
1369                 RPCRT4_new_client(cconn);
1370             else
1371                 return -1;
1372         }
1373
1374     return 1;
1375 }
1376
1377 #endif  /* HAVE_SOCKETPAIR */
1378
1379 static const struct connection_ops conn_protseq_list[] = {
1380   { "ncacn_np",
1381     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
1382     rpcrt4_conn_np_alloc,
1383     rpcrt4_ncacn_np_open,
1384     rpcrt4_ncacn_np_handoff,
1385     rpcrt4_conn_np_read,
1386     rpcrt4_conn_np_write,
1387     rpcrt4_conn_np_close,
1388     rpcrt4_conn_np_cancel_call,
1389     rpcrt4_conn_np_wait_for_incoming_data,
1390     rpcrt4_ncacn_np_get_top_of_tower,
1391     rpcrt4_ncacn_np_parse_top_of_tower,
1392   },
1393   { "ncalrpc",
1394     { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
1395     rpcrt4_conn_np_alloc,
1396     rpcrt4_ncalrpc_open,
1397     rpcrt4_ncalrpc_handoff,
1398     rpcrt4_conn_np_read,
1399     rpcrt4_conn_np_write,
1400     rpcrt4_conn_np_close,
1401     rpcrt4_conn_np_cancel_call,
1402     rpcrt4_conn_np_wait_for_incoming_data,
1403     rpcrt4_ncalrpc_get_top_of_tower,
1404     rpcrt4_ncalrpc_parse_top_of_tower,
1405   },
1406 #ifdef HAVE_SOCKETPAIR
1407   { "ncacn_ip_tcp",
1408     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
1409     rpcrt4_conn_tcp_alloc,
1410     rpcrt4_ncacn_ip_tcp_open,
1411     rpcrt4_conn_tcp_handoff,
1412     rpcrt4_conn_tcp_read,
1413     rpcrt4_conn_tcp_write,
1414     rpcrt4_conn_tcp_close,
1415     rpcrt4_conn_tcp_cancel_call,
1416     rpcrt4_conn_tcp_wait_for_incoming_data,
1417     rpcrt4_ncacn_ip_tcp_get_top_of_tower,
1418     rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
1419   }
1420 #endif
1421 };
1422
1423
1424 static const struct protseq_ops protseq_list[] =
1425 {
1426     {
1427         "ncacn_np",
1428         rpcrt4_protseq_np_alloc,
1429         rpcrt4_protseq_np_signal_state_changed,
1430         rpcrt4_protseq_np_get_wait_array,
1431         rpcrt4_protseq_np_free_wait_array,
1432         rpcrt4_protseq_np_wait_for_new_connection,
1433         rpcrt4_protseq_ncacn_np_open_endpoint,
1434     },
1435     {
1436         "ncalrpc",
1437         rpcrt4_protseq_np_alloc,
1438         rpcrt4_protseq_np_signal_state_changed,
1439         rpcrt4_protseq_np_get_wait_array,
1440         rpcrt4_protseq_np_free_wait_array,
1441         rpcrt4_protseq_np_wait_for_new_connection,
1442         rpcrt4_protseq_ncalrpc_open_endpoint,
1443     },
1444 #ifdef HAVE_SOCKETPAIR
1445     {
1446         "ncacn_ip_tcp",
1447         rpcrt4_protseq_sock_alloc,
1448         rpcrt4_protseq_sock_signal_state_changed,
1449         rpcrt4_protseq_sock_get_wait_array,
1450         rpcrt4_protseq_sock_free_wait_array,
1451         rpcrt4_protseq_sock_wait_for_new_connection,
1452         rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
1453     },
1454 #endif
1455 };
1456
1457 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
1458
1459 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
1460 {
1461   unsigned int i;
1462   for(i=0; i<ARRAYSIZE(protseq_list); i++)
1463     if (!strcmp(protseq_list[i].name, protseq))
1464       return &protseq_list[i];
1465   return NULL;
1466 }
1467
1468 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
1469 {
1470     unsigned int i;
1471     for(i=0; i<ARRAYSIZE(conn_protseq_list); i++)
1472         if (!strcmp(conn_protseq_list[i].name, protseq))
1473             return &conn_protseq_list[i];
1474     return NULL;
1475 }
1476
1477 /**** interface to rest of code ****/
1478
1479 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection)
1480 {
1481   TRACE("(Connection == ^%p)\n", Connection);
1482
1483   assert(!Connection->server);
1484   return Connection->ops->open_connection_client(Connection);
1485 }
1486
1487 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
1488 {
1489   TRACE("(Connection == ^%p)\n", Connection);
1490   if (SecIsValidHandle(&Connection->ctx))
1491   {
1492     DeleteSecurityContext(&Connection->ctx);
1493     SecInvalidateHandle(&Connection->ctx);
1494   }
1495   rpcrt4_conn_close(Connection);
1496   return RPC_S_OK;
1497 }
1498
1499 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
1500     LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
1501     LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
1502 {
1503   const struct connection_ops *ops;
1504   RpcConnection* NewConnection;
1505
1506   ops = rpcrt4_get_conn_protseq_ops(Protseq);
1507   if (!ops)
1508   {
1509     FIXME("not supported for protseq %s\n", Protseq);
1510     return RPC_S_PROTSEQ_NOT_SUPPORTED;
1511   }
1512
1513   NewConnection = ops->alloc();
1514   NewConnection->Next = NULL;
1515   NewConnection->server_binding = NULL;
1516   NewConnection->server = server;
1517   NewConnection->ops = ops;
1518   NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
1519   NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
1520   NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
1521   NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
1522   memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface));
1523   NewConnection->NextCallId = 1;
1524
1525   SecInvalidateHandle(&NewConnection->ctx);
1526   memset(&NewConnection->exp, 0, sizeof(NewConnection->exp));
1527   NewConnection->attr = 0;
1528   if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
1529   NewConnection->AuthInfo = AuthInfo;
1530   NewConnection->encryption_auth_len = 0;
1531   NewConnection->signature_auth_len = 0;
1532   if (QOS) RpcQualityOfService_AddRef(QOS);
1533   NewConnection->QOS = QOS;
1534
1535   list_init(&NewConnection->conn_pool_entry);
1536   NewConnection->async_state = NULL;
1537
1538   TRACE("connection: %p\n", NewConnection);
1539   *Connection = NewConnection;
1540
1541   return RPC_S_OK;
1542 }
1543
1544
1545 RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
1546 {
1547   RPC_STATUS err;
1548
1549   err = RPCRT4_CreateConnection(Connection, OldConnection->server,
1550                                 rpcrt4_conn_get_name(OldConnection),
1551                                 OldConnection->NetworkAddr,
1552                                 OldConnection->Endpoint, NULL,
1553                                 OldConnection->AuthInfo, OldConnection->QOS);
1554   if (err == RPC_S_OK)
1555     rpcrt4_conn_handoff(OldConnection, *Connection);
1556   return err;
1557 }
1558
1559 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
1560 {
1561   TRACE("connection: %p\n", Connection);
1562
1563   RPCRT4_CloseConnection(Connection);
1564   RPCRT4_strfree(Connection->Endpoint);
1565   RPCRT4_strfree(Connection->NetworkAddr);
1566   HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
1567   if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
1568   if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
1569
1570   /* server-only */
1571   if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
1572
1573   HeapFree(GetProcessHeap(), 0, Connection);
1574   return RPC_S_OK;
1575 }
1576
1577 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
1578                                       size_t *tower_size,
1579                                       const char *protseq,
1580                                       const char *networkaddr,
1581                                       const char *endpoint)
1582 {
1583     twr_empty_floor_t *protocol_floor;
1584     const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
1585
1586     *tower_size = 0;
1587
1588     if (!protseq_ops)
1589         return RPC_S_INVALID_RPC_PROTSEQ;
1590
1591     if (!tower_data)
1592     {
1593         *tower_size = sizeof(*protocol_floor);
1594         *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
1595         return RPC_S_OK;
1596     }
1597
1598     protocol_floor = (twr_empty_floor_t *)tower_data;
1599     protocol_floor->count_lhs = sizeof(protocol_floor->protid);
1600     protocol_floor->protid = protseq_ops->epm_protocols[0];
1601     protocol_floor->count_rhs = 0;
1602
1603     tower_data += sizeof(*protocol_floor);
1604
1605     *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
1606     if (!*tower_size)
1607         return EPT_S_NOT_REGISTERED;
1608
1609     *tower_size += sizeof(*protocol_floor);
1610
1611     return RPC_S_OK;
1612 }
1613
1614 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
1615                                         size_t tower_size,
1616                                         char **protseq,
1617                                         char **networkaddr,
1618                                         char **endpoint)
1619 {
1620     const twr_empty_floor_t *protocol_floor;
1621     const twr_empty_floor_t *floor4;
1622     const struct connection_ops *protseq_ops = NULL;
1623     RPC_STATUS status;
1624     unsigned int i;
1625
1626     if (tower_size < sizeof(*protocol_floor))
1627         return EPT_S_NOT_REGISTERED;
1628
1629     protocol_floor = (const twr_empty_floor_t *)tower_data;
1630     tower_data += sizeof(*protocol_floor);
1631     tower_size -= sizeof(*protocol_floor);
1632     if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
1633         (protocol_floor->count_rhs > tower_size))
1634         return EPT_S_NOT_REGISTERED;
1635     tower_data += protocol_floor->count_rhs;
1636     tower_size -= protocol_floor->count_rhs;
1637
1638     floor4 = (const twr_empty_floor_t *)tower_data;
1639     if ((tower_size < sizeof(*floor4)) ||
1640         (floor4->count_lhs != sizeof(floor4->protid)))
1641         return EPT_S_NOT_REGISTERED;
1642
1643     for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++)
1644         if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
1645             (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
1646         {
1647             protseq_ops = &conn_protseq_list[i];
1648             break;
1649         }
1650
1651     if (!protseq_ops)
1652         return EPT_S_NOT_REGISTERED;
1653
1654     status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
1655
1656     if ((status == RPC_S_OK) && protseq)
1657     {
1658         *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
1659         strcpy(*protseq, protseq_ops->name);
1660     }
1661
1662     return status;
1663 }
1664
1665 /***********************************************************************
1666  *             RpcNetworkIsProtseqValidW (RPCRT4.@)
1667  *
1668  * Checks if the given protocol sequence is known by the RPC system.
1669  * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
1670  *
1671  */
1672 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq)
1673 {
1674   char ps[0x10];
1675
1676   WideCharToMultiByte(CP_ACP, 0, protseq, -1,
1677                       ps, sizeof ps, NULL, NULL);
1678   if (rpcrt4_get_conn_protseq_ops(ps))
1679     return RPC_S_OK;
1680
1681   FIXME("Unknown protseq %s\n", debugstr_w(protseq));
1682
1683   return RPC_S_INVALID_RPC_PROTSEQ;
1684 }
1685
1686 /***********************************************************************
1687  *             RpcNetworkIsProtseqValidA (RPCRT4.@)
1688  */
1689 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq)
1690 {
1691   UNICODE_STRING protseqW;
1692
1693   if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
1694   {
1695     RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
1696     RtlFreeUnicodeString(&protseqW);
1697     return ret;
1698   }
1699   return RPC_S_OUT_OF_MEMORY;
1700 }