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