rpcrt4: RpcServerUseProtseqEp(..., NULL, ...) should return RPC_S_OK.
[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 "wininet.h"
75 #include "winternl.h"
76 #include "wine/unicode.h"
77
78 #include "rpc.h"
79 #include "rpcndr.h"
80
81 #include "wine/debug.h"
82
83 #include "rpc_binding.h"
84 #include "rpc_assoc.h"
85 #include "rpc_message.h"
86 #include "rpc_server.h"
87 #include "epm_towers.h"
88
89 #ifndef SOL_TCP
90 # define SOL_TCP IPPROTO_TCP
91 #endif
92
93 #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
94
95 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
96
97 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
98
99 /**** ncacn_np support ****/
100
101 typedef struct _RpcConnection_np
102 {
103   RpcConnection common;
104   HANDLE pipe;
105   OVERLAPPED ovl;
106   BOOL listening;
107 } RpcConnection_np;
108
109 static RpcConnection *rpcrt4_conn_np_alloc(void)
110 {
111   RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np));
112   if (npc)
113   {
114     npc->pipe = NULL;
115     memset(&npc->ovl, 0, sizeof(npc->ovl));
116     npc->listening = FALSE;
117   }
118   return &npc->common;
119 }
120
121 static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
122 {
123   if (npc->listening)
124     return RPC_S_OK;
125
126   npc->listening = TRUE;
127   for (;;)
128   {
129       if (ConnectNamedPipe(npc->pipe, &npc->ovl))
130           return RPC_S_OK;
131
132       switch(GetLastError())
133       {
134       case ERROR_PIPE_CONNECTED:
135           SetEvent(npc->ovl.hEvent);
136           return RPC_S_OK;
137       case ERROR_IO_PENDING:
138           /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */
139           return RPC_S_OK;
140       case ERROR_NO_DATA_DETECTED:
141           /* client has disconnected, retry */
142           DisconnectNamedPipe( npc->pipe );
143           break;
144       default:
145           npc->listening = FALSE;
146           WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());
147           return RPC_S_OUT_OF_RESOURCES;
148       }
149   }
150 }
151
152 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
153 {
154   RpcConnection_np *npc = (RpcConnection_np *) Connection;
155   TRACE("listening on %s\n", pname);
156
157   npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX,
158                                PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
159                                PIPE_UNLIMITED_INSTANCES,
160                                RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
161   if (npc->pipe == INVALID_HANDLE_VALUE) {
162     WARN("CreateNamedPipe failed with error %d\n", GetLastError());
163     if (GetLastError() == ERROR_FILE_EXISTS)
164       return RPC_S_DUPLICATE_ENDPOINT;
165     else
166       return RPC_S_CANT_CREATE_ENDPOINT;
167   }
168
169   memset(&npc->ovl, 0, sizeof(npc->ovl));
170   npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
171
172   /* Note: we don't call ConnectNamedPipe here because it must be done in the
173    * server thread as the thread must be alertable */
174   return RPC_S_OK;
175 }
176
177 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait)
178 {
179   RpcConnection_np *npc = (RpcConnection_np *) Connection;
180   HANDLE pipe;
181   DWORD err, dwMode;
182
183   TRACE("connecting to %s\n", pname);
184
185   while (TRUE) {
186     DWORD dwFlags = 0;
187     if (Connection->QOS)
188     {
189         dwFlags = SECURITY_SQOS_PRESENT;
190         switch (Connection->QOS->qos->ImpersonationType)
191         {
192             case RPC_C_IMP_LEVEL_DEFAULT:
193                 /* FIXME: what to do here? */
194                 break;
195             case RPC_C_IMP_LEVEL_ANONYMOUS:
196                 dwFlags |= SECURITY_ANONYMOUS;
197                 break;
198             case RPC_C_IMP_LEVEL_IDENTIFY:
199                 dwFlags |= SECURITY_IDENTIFICATION;
200                 break;
201             case RPC_C_IMP_LEVEL_IMPERSONATE:
202                 dwFlags |= SECURITY_IMPERSONATION;
203                 break;
204             case RPC_C_IMP_LEVEL_DELEGATE:
205                 dwFlags |= SECURITY_DELEGATION;
206                 break;
207         }
208         if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTIFY_DYNAMIC)
209             dwFlags |= SECURITY_CONTEXT_TRACKING;
210     }
211     pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
212                        OPEN_EXISTING, dwFlags, 0);
213     if (pipe != INVALID_HANDLE_VALUE) break;
214     err = GetLastError();
215     if (err == ERROR_PIPE_BUSY) {
216       TRACE("connection failed, error=%x\n", err);
217       return RPC_S_SERVER_TOO_BUSY;
218     }
219     if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
220       err = GetLastError();
221       WARN("connection failed, error=%x\n", err);
222       return RPC_S_SERVER_UNAVAILABLE;
223     }
224   }
225
226   /* success */
227   memset(&npc->ovl, 0, sizeof(npc->ovl));
228   /* pipe is connected; change to message-read mode. */
229   dwMode = PIPE_READMODE_MESSAGE;
230   SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
231   npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
232   npc->pipe = pipe;
233
234   return RPC_S_OK;
235 }
236
237 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection)
238 {
239   RpcConnection_np *npc = (RpcConnection_np *) Connection;
240   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
241   RPC_STATUS r;
242   LPSTR pname;
243
244   /* already connected? */
245   if (npc->pipe)
246     return RPC_S_OK;
247
248   /* protseq=ncalrpc: supposed to use NT LPC ports,
249    * but we'll implement it with named pipes for now */
250   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
251   strcat(strcpy(pname, prefix), Connection->Endpoint);
252   r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
253   I_RpcFree(pname);
254
255   return r;
256 }
257
258 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint)
259 {
260   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
261   RPC_STATUS r;
262   LPSTR pname;
263   RpcConnection *Connection;
264   char generated_endpoint[22];
265
266   if (!endpoint)
267   {
268     static LONG lrpc_nameless_id;
269     DWORD process_id = GetCurrentProcessId();
270     ULONG id = InterlockedIncrement(&lrpc_nameless_id);
271     snprintf(generated_endpoint, sizeof(generated_endpoint),
272              "LRPC%08x.%08x", process_id, id);
273     endpoint = generated_endpoint;
274   }
275
276   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
277                               endpoint, NULL, NULL, NULL);
278   if (r != RPC_S_OK)
279       return r;
280
281   /* protseq=ncalrpc: supposed to use NT LPC ports,
282    * but we'll implement it with named pipes for now */
283   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
284   strcat(strcpy(pname, prefix), Connection->Endpoint);
285   r = rpcrt4_conn_create_pipe(Connection, pname);
286   I_RpcFree(pname);
287
288   EnterCriticalSection(&protseq->cs);
289   Connection->Next = protseq->conn;
290   protseq->conn = Connection;
291   LeaveCriticalSection(&protseq->cs);
292
293   return r;
294 }
295
296 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
297 {
298   RpcConnection_np *npc = (RpcConnection_np *) Connection;
299   static const char prefix[] = "\\\\.";
300   RPC_STATUS r;
301   LPSTR pname;
302
303   /* already connected? */
304   if (npc->pipe)
305     return RPC_S_OK;
306
307   /* protseq=ncacn_np: named pipes */
308   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
309   strcat(strcpy(pname, prefix), Connection->Endpoint);
310   r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
311   I_RpcFree(pname);
312
313   return r;
314 }
315
316 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
317 {
318   static const char prefix[] = "\\\\.";
319   RPC_STATUS r;
320   LPSTR pname;
321   RpcConnection *Connection;
322   char generated_endpoint[21];
323
324   if (!endpoint)
325   {
326     static LONG np_nameless_id;
327     DWORD process_id = GetCurrentProcessId();
328     ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 );
329     snprintf(generated_endpoint, sizeof(generated_endpoint),
330              "\\\\pipe\\\\%08x.%03x", process_id, id);
331     endpoint = generated_endpoint;
332   }
333
334   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
335                               endpoint, NULL, NULL, NULL);
336   if (r != RPC_S_OK)
337     return r;
338
339   /* protseq=ncacn_np: named pipes */
340   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
341   strcat(strcpy(pname, prefix), Connection->Endpoint);
342   r = rpcrt4_conn_create_pipe(Connection, pname);
343   I_RpcFree(pname);
344
345   EnterCriticalSection(&protseq->cs);
346   Connection->Next = protseq->conn;
347   protseq->conn = Connection;
348   LeaveCriticalSection(&protseq->cs);
349
350   return r;
351 }
352
353 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc)
354 {    
355   /* because of the way named pipes work, we'll transfer the connected pipe
356    * to the child, then reopen the server binding to continue listening */
357
358   new_npc->pipe = old_npc->pipe;
359   new_npc->ovl = old_npc->ovl;
360   old_npc->pipe = 0;
361   memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));
362   old_npc->listening = FALSE;
363 }
364
365 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
366 {
367   RPC_STATUS status;
368   LPSTR pname;
369   static const char prefix[] = "\\\\.";
370
371   rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
372
373   pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
374   strcat(strcpy(pname, prefix), old_conn->Endpoint);
375   status = rpcrt4_conn_create_pipe(old_conn, pname);
376   I_RpcFree(pname);
377
378   return status;
379 }
380
381 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
382 {
383   RPC_STATUS status;
384   LPSTR pname;
385   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
386
387   TRACE("%s\n", old_conn->Endpoint);
388
389   rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
390
391   pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
392   strcat(strcpy(pname, prefix), old_conn->Endpoint);
393   status = rpcrt4_conn_create_pipe(old_conn, pname);
394   I_RpcFree(pname);
395     
396   return status;
397 }
398
399 static int rpcrt4_conn_np_read(RpcConnection *Connection,
400                         void *buffer, unsigned int count)
401 {
402   RpcConnection_np *npc = (RpcConnection_np *) Connection;
403   char *buf = buffer;
404   BOOL ret = TRUE;
405   unsigned int bytes_left = count;
406
407   while (bytes_left)
408   {
409     DWORD bytes_read;
410     ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, NULL);
411     if (!ret && GetLastError() == ERROR_MORE_DATA)
412         ret = TRUE;
413     if (!ret || !bytes_read)
414         break;
415     bytes_left -= bytes_read;
416     buf += bytes_read;
417   }
418   return ret ? count : -1;
419 }
420
421 static int rpcrt4_conn_np_write(RpcConnection *Connection,
422                              const void *buffer, unsigned int count)
423 {
424   RpcConnection_np *npc = (RpcConnection_np *) Connection;
425   const char *buf = buffer;
426   BOOL ret = TRUE;
427   unsigned int bytes_left = count;
428
429   while (bytes_left)
430   {
431     DWORD bytes_written;
432     ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, NULL);
433     if (!ret || !bytes_written)
434         break;
435     bytes_left -= bytes_written;
436     buf += bytes_written;
437   }
438   return ret ? count : -1;
439 }
440
441 static int rpcrt4_conn_np_close(RpcConnection *Connection)
442 {
443   RpcConnection_np *npc = (RpcConnection_np *) Connection;
444   if (npc->pipe) {
445     FlushFileBuffers(npc->pipe);
446     CloseHandle(npc->pipe);
447     npc->pipe = 0;
448   }
449   if (npc->ovl.hEvent) {
450     CloseHandle(npc->ovl.hEvent);
451     npc->ovl.hEvent = 0;
452   }
453   return 0;
454 }
455
456 static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection)
457 {
458     /* FIXME: implement when named pipe writes use overlapped I/O */
459 }
460
461 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection)
462 {
463     /* FIXME: implement when named pipe writes use overlapped I/O */
464     return -1;
465 }
466
467 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
468                                                const char *networkaddr,
469                                                const char *endpoint)
470 {
471     twr_empty_floor_t *smb_floor;
472     twr_empty_floor_t *nb_floor;
473     size_t size;
474     size_t networkaddr_size;
475     size_t endpoint_size;
476
477     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
478
479     networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
480     endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
481     size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
482
483     if (!tower_data)
484         return size;
485
486     smb_floor = (twr_empty_floor_t *)tower_data;
487
488     tower_data += sizeof(*smb_floor);
489
490     smb_floor->count_lhs = sizeof(smb_floor->protid);
491     smb_floor->protid = EPM_PROTOCOL_SMB;
492     smb_floor->count_rhs = endpoint_size;
493
494     if (endpoint)
495         memcpy(tower_data, endpoint, endpoint_size);
496     else
497         tower_data[0] = 0;
498     tower_data += endpoint_size;
499
500     nb_floor = (twr_empty_floor_t *)tower_data;
501
502     tower_data += sizeof(*nb_floor);
503
504     nb_floor->count_lhs = sizeof(nb_floor->protid);
505     nb_floor->protid = EPM_PROTOCOL_NETBIOS;
506     nb_floor->count_rhs = networkaddr_size;
507
508     if (networkaddr)
509         memcpy(tower_data, networkaddr, networkaddr_size);
510     else
511         tower_data[0] = 0;
512
513     return size;
514 }
515
516 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
517                                                      size_t tower_size,
518                                                      char **networkaddr,
519                                                      char **endpoint)
520 {
521     const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
522     const twr_empty_floor_t *nb_floor;
523
524     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
525
526     if (tower_size < sizeof(*smb_floor))
527         return EPT_S_NOT_REGISTERED;
528
529     tower_data += sizeof(*smb_floor);
530     tower_size -= sizeof(*smb_floor);
531
532     if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
533         (smb_floor->protid != EPM_PROTOCOL_SMB) ||
534         (smb_floor->count_rhs > tower_size) ||
535         (tower_data[smb_floor->count_rhs - 1] != '\0'))
536         return EPT_S_NOT_REGISTERED;
537
538     if (endpoint)
539     {
540         *endpoint = I_RpcAllocate(smb_floor->count_rhs);
541         if (!*endpoint)
542             return RPC_S_OUT_OF_RESOURCES;
543         memcpy(*endpoint, tower_data, smb_floor->count_rhs);
544     }
545     tower_data += smb_floor->count_rhs;
546     tower_size -= smb_floor->count_rhs;
547
548     if (tower_size < sizeof(*nb_floor))
549         return EPT_S_NOT_REGISTERED;
550
551     nb_floor = (const twr_empty_floor_t *)tower_data;
552
553     tower_data += sizeof(*nb_floor);
554     tower_size -= sizeof(*nb_floor);
555
556     if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
557         (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
558         (nb_floor->count_rhs > tower_size) ||
559         (tower_data[nb_floor->count_rhs - 1] != '\0'))
560         return EPT_S_NOT_REGISTERED;
561
562     if (networkaddr)
563     {
564         *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
565         if (!*networkaddr)
566         {
567             if (endpoint)
568             {
569                 I_RpcFree(*endpoint);
570                 *endpoint = NULL;
571             }
572             return RPC_S_OUT_OF_RESOURCES;
573         }
574         memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
575     }
576
577     return RPC_S_OK;
578 }
579
580 typedef struct _RpcServerProtseq_np
581 {
582     RpcServerProtseq common;
583     HANDLE mgr_event;
584 } RpcServerProtseq_np;
585
586 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void)
587 {
588     RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
589     if (ps)
590         ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
591     return &ps->common;
592 }
593
594 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
595 {
596     RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
597     SetEvent(npps->mgr_event);
598 }
599
600 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
601 {
602     HANDLE *objs = prev_array;
603     RpcConnection_np *conn;
604     RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
605     
606     EnterCriticalSection(&protseq->cs);
607     
608     /* open and count connections */
609     *count = 1;
610     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
611     while (conn) {
612         rpcrt4_conn_listen_pipe(conn);
613         if (conn->ovl.hEvent)
614             (*count)++;
615         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
616     }
617     
618     /* make array of connections */
619     if (objs)
620         objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
621     else
622         objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
623     if (!objs)
624     {
625         ERR("couldn't allocate objs\n");
626         LeaveCriticalSection(&protseq->cs);
627         return NULL;
628     }
629     
630     objs[0] = npps->mgr_event;
631     *count = 1;
632     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
633     while (conn) {
634         if ((objs[*count] = conn->ovl.hEvent))
635             (*count)++;
636         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
637     }
638     LeaveCriticalSection(&protseq->cs);
639     return objs;
640 }
641
642 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array)
643 {
644     HeapFree(GetProcessHeap(), 0, array);
645 }
646
647 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
648 {
649     HANDLE b_handle;
650     HANDLE *objs = wait_array;
651     DWORD res;
652     RpcConnection *cconn;
653     RpcConnection_np *conn;
654     
655     if (!objs)
656         return -1;
657
658     do
659     {
660         /* an alertable wait isn't strictly necessary, but due to our
661          * overlapped I/O implementation in Wine we need to free some memory
662          * by the file user APC being called, even if no completion routine was
663          * specified at the time of starting the async operation */
664         res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
665     } while (res == WAIT_IO_COMPLETION);
666
667     if (res == WAIT_OBJECT_0)
668         return 0;
669     else if (res == WAIT_FAILED)
670     {
671         ERR("wait failed with error %d\n", GetLastError());
672         return -1;
673     }
674     else
675     {
676         b_handle = objs[res - WAIT_OBJECT_0];
677         /* find which connection got a RPC */
678         EnterCriticalSection(&protseq->cs);
679         conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
680         while (conn) {
681             if (b_handle == conn->ovl.hEvent) break;
682             conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
683         }
684         cconn = NULL;
685         if (conn)
686             RPCRT4_SpawnConnection(&cconn, &conn->common);
687         else
688             ERR("failed to locate connection for handle %p\n", b_handle);
689         LeaveCriticalSection(&protseq->cs);
690         if (cconn)
691         {
692             RPCRT4_new_client(cconn);
693             return 1;
694         }
695         else return -1;
696     }
697 }
698
699 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
700                                               const char *networkaddr,
701                                               const char *endpoint)
702 {
703     twr_empty_floor_t *pipe_floor;
704     size_t size;
705     size_t endpoint_size;
706
707     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
708
709     endpoint_size = strlen(endpoint) + 1;
710     size = sizeof(*pipe_floor) + endpoint_size;
711
712     if (!tower_data)
713         return size;
714
715     pipe_floor = (twr_empty_floor_t *)tower_data;
716
717     tower_data += sizeof(*pipe_floor);
718
719     pipe_floor->count_lhs = sizeof(pipe_floor->protid);
720     pipe_floor->protid = EPM_PROTOCOL_PIPE;
721     pipe_floor->count_rhs = endpoint_size;
722
723     memcpy(tower_data, endpoint, endpoint_size);
724
725     return size;
726 }
727
728 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
729                                                     size_t tower_size,
730                                                     char **networkaddr,
731                                                     char **endpoint)
732 {
733     const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
734
735     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
736
737     if (tower_size < sizeof(*pipe_floor))
738         return EPT_S_NOT_REGISTERED;
739
740     tower_data += sizeof(*pipe_floor);
741     tower_size -= sizeof(*pipe_floor);
742
743     if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
744         (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
745         (pipe_floor->count_rhs > tower_size) ||
746         (tower_data[pipe_floor->count_rhs - 1] != '\0'))
747         return EPT_S_NOT_REGISTERED;
748
749     if (networkaddr)
750         *networkaddr = NULL;
751
752     if (endpoint)
753     {
754         *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
755         if (!*endpoint)
756             return RPC_S_OUT_OF_RESOURCES;
757         memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
758     }
759
760     return RPC_S_OK;
761 }
762
763 /**** ncacn_ip_tcp support ****/
764
765 #ifdef HAVE_SOCKETPAIR
766
767 typedef struct _RpcConnection_tcp
768 {
769   RpcConnection common;
770   int sock;
771   int cancel_fds[2];
772 } RpcConnection_tcp;
773
774 static RpcConnection *rpcrt4_conn_tcp_alloc(void)
775 {
776   RpcConnection_tcp *tcpc;
777   tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp));
778   if (tcpc == NULL)
779     return NULL;
780   tcpc->sock = -1;
781   if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
782   {
783     ERR("socketpair() failed: %s\n", strerror(errno));
784     HeapFree(GetProcessHeap(), 0, tcpc);
785     return NULL;
786   }
787   return &tcpc->common;
788 }
789
790 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
791 {
792   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
793   int sock;
794   int ret;
795   struct addrinfo *ai;
796   struct addrinfo *ai_cur;
797   struct addrinfo hints;
798
799   TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
800
801   if (tcpc->sock != -1)
802     return RPC_S_OK;
803
804   hints.ai_flags          = 0;
805   hints.ai_family         = PF_UNSPEC;
806   hints.ai_socktype       = SOCK_STREAM;
807   hints.ai_protocol       = IPPROTO_TCP;
808   hints.ai_addrlen        = 0;
809   hints.ai_addr           = NULL;
810   hints.ai_canonname      = NULL;
811   hints.ai_next           = NULL;
812
813   ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
814   if (ret)
815   {
816     ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
817       Connection->Endpoint, gai_strerror(ret));
818     return RPC_S_SERVER_UNAVAILABLE;
819   }
820
821   for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
822   {
823     int val;
824
825     if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
826     {
827       TRACE("skipping non-IP/IPv6 address family\n");
828       continue;
829     }
830
831     if (TRACE_ON(rpc))
832     {
833       char host[256];
834       char service[256];
835       getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
836         host, sizeof(host), service, sizeof(service),
837         NI_NUMERICHOST | NI_NUMERICSERV);
838       TRACE("trying %s:%s\n", host, service);
839     }
840
841     sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
842     if (sock == -1)
843     {
844       WARN("socket() failed: %s\n", strerror(errno));
845       continue;
846     }
847
848     if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
849     {
850       WARN("connect() failed: %s\n", strerror(errno));
851       closesocket(sock);
852       continue;
853     }
854
855     /* RPC depends on having minimal latency so disable the Nagle algorithm */
856     val = 1;
857     setsockopt(sock, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
858     fcntl(sock, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
859
860     tcpc->sock = sock;
861
862     freeaddrinfo(ai);
863     TRACE("connected\n");
864     return RPC_S_OK;
865   }
866
867   freeaddrinfo(ai);
868   ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
869   return RPC_S_SERVER_UNAVAILABLE;
870 }
871
872 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
873 {
874     RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
875     int sock;
876     int ret;
877     struct addrinfo *ai;
878     struct addrinfo *ai_cur;
879     struct addrinfo hints;
880     RpcConnection *first_connection = NULL;
881
882     TRACE("(%p, %s)\n", protseq, endpoint);
883
884     hints.ai_flags          = AI_PASSIVE /* for non-localhost addresses */;
885     hints.ai_family         = PF_UNSPEC;
886     hints.ai_socktype       = SOCK_STREAM;
887     hints.ai_protocol       = IPPROTO_TCP;
888     hints.ai_addrlen        = 0;
889     hints.ai_addr           = NULL;
890     hints.ai_canonname      = NULL;
891     hints.ai_next           = NULL;
892
893     ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai);
894     if (ret)
895     {
896         ERR("getaddrinfo for port %s failed: %s\n", endpoint,
897             gai_strerror(ret));
898         if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
899             return RPC_S_INVALID_ENDPOINT_FORMAT;
900         return RPC_S_CANT_CREATE_ENDPOINT;
901     }
902
903     for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
904     {
905         RpcConnection_tcp *tcpc;
906         RPC_STATUS create_status;
907         struct sockaddr_storage sa;
908         socklen_t sa_len;
909         char service[NI_MAXSERV];
910
911         if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
912         {
913             TRACE("skipping non-IP/IPv6 address family\n");
914             continue;
915         }
916
917         if (TRACE_ON(rpc))
918         {
919             char host[256];
920             getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
921                         host, sizeof(host), service, sizeof(service),
922                         NI_NUMERICHOST | NI_NUMERICSERV);
923             TRACE("trying %s:%s\n", host, service);
924         }
925
926         sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
927         if (sock == -1)
928         {
929             WARN("socket() failed: %s\n", strerror(errno));
930             status = RPC_S_CANT_CREATE_ENDPOINT;
931             continue;
932         }
933
934         ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
935         if (ret < 0)
936         {
937             WARN("bind failed: %s\n", strerror(errno));
938             closesocket(sock);
939             if (errno == EADDRINUSE)
940               status = RPC_S_DUPLICATE_ENDPOINT;
941             else
942               status = RPC_S_CANT_CREATE_ENDPOINT;
943             continue;
944         }
945
946         sa_len = sizeof(sa);
947         if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
948         {
949             WARN("getsockname() failed: %s\n", strerror(errno));
950             status = RPC_S_CANT_CREATE_ENDPOINT;
951             continue;
952         }
953
954         ret = getnameinfo((struct sockaddr *)&sa, sa_len,
955                           NULL, 0, service, sizeof(service),
956                           NI_NUMERICSERV);
957         if (ret)
958         {
959             WARN("getnameinfo failed: %s\n", gai_strerror(ret));
960             status = RPC_S_CANT_CREATE_ENDPOINT;
961             continue;
962         }
963
964         create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
965                                                 protseq->Protseq, NULL,
966                                                 service, NULL, NULL, NULL);
967         if (create_status != RPC_S_OK)
968         {
969             closesocket(sock);
970             status = create_status;
971             continue;
972         }
973
974         tcpc->sock = sock;
975         ret = listen(sock, protseq->MaxCalls);
976         if (ret < 0)
977         {
978             WARN("listen failed: %s\n", strerror(errno));
979             RPCRT4_DestroyConnection(&tcpc->common);
980             status = RPC_S_OUT_OF_RESOURCES;
981             continue;
982         }
983         /* need a non-blocking socket, otherwise accept() has a potential
984          * race-condition (poll() says it is readable, connection drops,
985          * and accept() blocks until the next connection comes...)
986          */
987         ret = fcntl(sock, F_SETFL, O_NONBLOCK);
988         if (ret < 0)
989         {
990             WARN("couldn't make socket non-blocking, error %d\n", ret);
991             RPCRT4_DestroyConnection(&tcpc->common);
992             status = RPC_S_OUT_OF_RESOURCES;
993             continue;
994         }
995
996         tcpc->common.Next = first_connection;
997         first_connection = &tcpc->common;
998
999         /* since IPv4 and IPv6 share the same port space, we only need one
1000          * successful bind to listen for both */
1001         break;
1002     }
1003
1004     freeaddrinfo(ai);
1005
1006     /* if at least one connection was created for an endpoint then
1007      * return success */
1008     if (first_connection)
1009     {
1010         RpcConnection *conn;
1011
1012         /* find last element in list */
1013         for (conn = first_connection; conn->Next; conn = conn->Next)
1014             ;
1015
1016         EnterCriticalSection(&protseq->cs);
1017         conn->Next = protseq->conn;
1018         protseq->conn = first_connection;
1019         LeaveCriticalSection(&protseq->cs);
1020         
1021         TRACE("listening on %s\n", endpoint);
1022         return RPC_S_OK;
1023     }
1024
1025     ERR("couldn't listen on port %s\n", endpoint);
1026     return status;
1027 }
1028
1029 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
1030 {
1031   int ret;
1032   struct sockaddr_in address;
1033   socklen_t addrsize;
1034   RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;
1035   RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;
1036
1037   addrsize = sizeof(address);
1038   ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
1039   if (ret < 0)
1040   {
1041     ERR("Failed to accept a TCP connection: error %d\n", ret);
1042     return RPC_S_OUT_OF_RESOURCES;
1043   }
1044   /* reset to blocking behaviour */
1045   fcntl(ret, F_SETFL, 0);
1046   client->sock = ret;
1047   TRACE("Accepted a new TCP connection\n");
1048   return RPC_S_OK;
1049 }
1050
1051 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
1052                                 void *buffer, unsigned int count)
1053 {
1054   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1055   int bytes_read = 0;
1056   do
1057   {
1058     int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
1059     if (!r)
1060       return -1;
1061     else if (r > 0)
1062       bytes_read += r;
1063     else if (errno != EAGAIN)
1064     {
1065       WARN("recv() failed: %s\n", strerror(errno));
1066       return -1;
1067     }
1068     else
1069     {
1070       struct pollfd pfds[2];
1071       pfds[0].fd = tcpc->sock;
1072       pfds[0].events = POLLIN;
1073       pfds[1].fd = tcpc->cancel_fds[0];
1074       pfds[1].events = POLLIN;
1075       if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1076       {
1077         ERR("poll() failed: %s\n", strerror(errno));
1078         return -1;
1079       }
1080       if (pfds[1].revents & POLLIN) /* canceled */
1081       {
1082         char dummy;
1083         read(pfds[1].fd, &dummy, sizeof(dummy));
1084         return -1;
1085       }
1086     }
1087   } while (bytes_read != count);
1088   TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1089   return bytes_read;
1090 }
1091
1092 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1093                                  const void *buffer, unsigned int count)
1094 {
1095   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1096   int bytes_written = 0;
1097   do
1098   {
1099     int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1100     if (r >= 0)
1101       bytes_written += r;
1102     else if (errno != EAGAIN)
1103       return -1;
1104     else
1105     {
1106       struct pollfd pfd;
1107       pfd.fd = tcpc->sock;
1108       pfd.events = POLLOUT;
1109       if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
1110       {
1111         ERR("poll() failed: %s\n", strerror(errno));
1112         return -1;
1113       }
1114     }
1115   } while (bytes_written != count);
1116   TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1117   return bytes_written;
1118 }
1119
1120 static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
1121 {
1122   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1123
1124   TRACE("%d\n", tcpc->sock);
1125
1126   if (tcpc->sock != -1)
1127     closesocket(tcpc->sock);
1128   tcpc->sock = -1;
1129   close(tcpc->cancel_fds[0]);
1130   close(tcpc->cancel_fds[1]);
1131   return 0;
1132 }
1133
1134 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
1135 {
1136     RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1137     char dummy = 1;
1138
1139     TRACE("%p\n", Connection);
1140
1141     write(tcpc->cancel_fds[1], &dummy, 1);
1142 }
1143
1144 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
1145 {
1146     RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1147     struct pollfd pfds[2];
1148
1149     TRACE("%p\n", Connection);
1150
1151     pfds[0].fd = tcpc->sock;
1152     pfds[0].events = POLLIN;
1153     pfds[1].fd = tcpc->cancel_fds[0];
1154     pfds[1].events = POLLIN;
1155     if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1156     {
1157       ERR("poll() failed: %s\n", strerror(errno));
1158       return -1;
1159     }
1160     if (pfds[1].revents & POLLIN) /* canceled */
1161     {
1162       char dummy;
1163       read(pfds[1].fd, &dummy, sizeof(dummy));
1164       return -1;
1165     }
1166
1167     return 0;
1168 }
1169
1170 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1171                                              const char *networkaddr,
1172                                              unsigned char tcp_protid,
1173                                              const char *endpoint)
1174 {
1175     twr_tcp_floor_t *tcp_floor;
1176     twr_ipv4_floor_t *ipv4_floor;
1177     struct addrinfo *ai;
1178     struct addrinfo hints;
1179     int ret;
1180     size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
1181
1182     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
1183
1184     if (!tower_data)
1185         return size;
1186
1187     tcp_floor = (twr_tcp_floor_t *)tower_data;
1188     tower_data += sizeof(*tcp_floor);
1189
1190     ipv4_floor = (twr_ipv4_floor_t *)tower_data;
1191
1192     tcp_floor->count_lhs = sizeof(tcp_floor->protid);
1193     tcp_floor->protid = tcp_protid;
1194     tcp_floor->count_rhs = sizeof(tcp_floor->port);
1195
1196     ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
1197     ipv4_floor->protid = EPM_PROTOCOL_IP;
1198     ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
1199
1200     hints.ai_flags          = AI_NUMERICHOST;
1201     /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
1202     hints.ai_family         = PF_INET;
1203     hints.ai_socktype       = SOCK_STREAM;
1204     hints.ai_protocol       = IPPROTO_TCP;
1205     hints.ai_addrlen        = 0;
1206     hints.ai_addr           = NULL;
1207     hints.ai_canonname      = NULL;
1208     hints.ai_next           = NULL;
1209
1210     ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
1211     if (ret)
1212     {
1213         ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
1214         if (ret)
1215         {
1216             ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
1217             return 0;
1218         }
1219     }
1220
1221     if (ai->ai_family == PF_INET)
1222     {
1223         const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
1224         tcp_floor->port = sin->sin_port;
1225         ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
1226     }
1227     else
1228     {
1229         ERR("unexpected protocol family %d\n", ai->ai_family);
1230         return 0;
1231     }
1232
1233     freeaddrinfo(ai);
1234
1235     return size;
1236 }
1237
1238 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1239                                                    const char *networkaddr,
1240                                                    const char *endpoint)
1241 {
1242     return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
1243                                           EPM_PROTOCOL_TCP, endpoint);
1244 }
1245
1246 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1247                                                    size_t tower_size,
1248                                                    char **networkaddr,
1249                                                    unsigned char tcp_protid,
1250                                                    char **endpoint)
1251 {
1252     const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
1253     const twr_ipv4_floor_t *ipv4_floor;
1254     struct in_addr in_addr;
1255
1256     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
1257
1258     if (tower_size < sizeof(*tcp_floor))
1259         return EPT_S_NOT_REGISTERED;
1260
1261     tower_data += sizeof(*tcp_floor);
1262     tower_size -= sizeof(*tcp_floor);
1263
1264     if (tower_size < sizeof(*ipv4_floor))
1265         return EPT_S_NOT_REGISTERED;
1266
1267     ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
1268
1269     if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
1270         (tcp_floor->protid != tcp_protid) ||
1271         (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
1272         (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
1273         (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
1274         (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
1275         return EPT_S_NOT_REGISTERED;
1276
1277     if (endpoint)
1278     {
1279         *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
1280         if (!*endpoint)
1281             return RPC_S_OUT_OF_RESOURCES;
1282         sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
1283     }
1284
1285     if (networkaddr)
1286     {
1287         *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
1288         if (!*networkaddr)
1289         {
1290             if (endpoint)
1291             {
1292                 I_RpcFree(*endpoint);
1293                 *endpoint = NULL;
1294             }
1295             return RPC_S_OUT_OF_RESOURCES;
1296         }
1297         in_addr.s_addr = ipv4_floor->ipv4addr;
1298         if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
1299         {
1300             ERR("inet_ntop: %s\n", strerror(errno));
1301             I_RpcFree(*networkaddr);
1302             *networkaddr = NULL;
1303             if (endpoint)
1304             {
1305                 I_RpcFree(*endpoint);
1306                 *endpoint = NULL;
1307             }
1308             return EPT_S_NOT_REGISTERED;
1309         }
1310     }
1311
1312     return RPC_S_OK;
1313 }
1314
1315 typedef struct _RpcServerProtseq_sock
1316 {
1317     RpcServerProtseq common;
1318     int mgr_event_rcv;
1319     int mgr_event_snd;
1320 } RpcServerProtseq_sock;
1321
1322 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1323 {
1324     RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1325     if (ps)
1326     {
1327         int fds[2];
1328         if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))
1329         {
1330             fcntl(fds[0], F_SETFL, O_NONBLOCK);
1331             fcntl(fds[1], F_SETFL, O_NONBLOCK);
1332             ps->mgr_event_rcv = fds[0];
1333             ps->mgr_event_snd = fds[1];
1334         }
1335         else
1336         {
1337             ERR("socketpair failed with error %s\n", strerror(errno));
1338             HeapFree(GetProcessHeap(), 0, ps);
1339             return NULL;
1340         }
1341     }
1342     return &ps->common;
1343 }
1344
1345 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1346 {
1347     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1348     char dummy = 1;
1349     write(sockps->mgr_event_snd, &dummy, sizeof(dummy));
1350 }
1351
1352 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1353 {
1354     struct pollfd *poll_info = prev_array;
1355     RpcConnection_tcp *conn;
1356     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1357
1358     EnterCriticalSection(&protseq->cs);
1359     
1360     /* open and count connections */
1361     *count = 1;
1362     conn = (RpcConnection_tcp *)protseq->conn;
1363     while (conn) {
1364         if (conn->sock != -1)
1365             (*count)++;
1366         conn = (RpcConnection_tcp *)conn->common.Next;
1367     }
1368     
1369     /* make array of connections */
1370     if (poll_info)
1371         poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));
1372     else
1373         poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));
1374     if (!poll_info)
1375     {
1376         ERR("couldn't allocate poll_info\n");
1377         LeaveCriticalSection(&protseq->cs);
1378         return NULL;
1379     }
1380
1381     poll_info[0].fd = sockps->mgr_event_rcv;
1382     poll_info[0].events = POLLIN;
1383     *count = 1;
1384     conn =  CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1385     while (conn) {
1386         if (conn->sock != -1)
1387         {
1388             poll_info[*count].fd = conn->sock;
1389             poll_info[*count].events = POLLIN;
1390             (*count)++;
1391         }
1392         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1393     }
1394     LeaveCriticalSection(&protseq->cs);
1395     return poll_info;
1396 }
1397
1398 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1399 {
1400     HeapFree(GetProcessHeap(), 0, array);
1401 }
1402
1403 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1404 {
1405     struct pollfd *poll_info = wait_array;
1406     int ret;
1407     unsigned int i;
1408     RpcConnection *cconn;
1409     RpcConnection_tcp *conn;
1410     
1411     if (!poll_info)
1412         return -1;
1413     
1414     ret = poll(poll_info, count, -1);
1415     if (ret < 0)
1416     {
1417         ERR("poll failed with error %d\n", ret);
1418         return -1;
1419     }
1420
1421     for (i = 0; i < count; i++)
1422         if (poll_info[i].revents & POLLIN)
1423         {
1424             /* RPC server event */
1425             if (i == 0)
1426             {
1427                 char dummy;
1428                 read(poll_info[0].fd, &dummy, sizeof(dummy));
1429                 return 0;
1430             }
1431
1432             /* find which connection got a RPC */
1433             EnterCriticalSection(&protseq->cs);
1434             conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1435             while (conn) {
1436                 if (poll_info[i].fd == conn->sock) break;
1437                 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1438             }
1439             cconn = NULL;
1440             if (conn)
1441                 RPCRT4_SpawnConnection(&cconn, &conn->common);
1442             else
1443                 ERR("failed to locate connection for fd %d\n", poll_info[i].fd);
1444             LeaveCriticalSection(&protseq->cs);
1445             if (cconn)
1446                 RPCRT4_new_client(cconn);
1447             else
1448                 return -1;
1449         }
1450
1451     return 1;
1452 }
1453
1454 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1455                                                          size_t tower_size,
1456                                                          char **networkaddr,
1457                                                          char **endpoint)
1458 {
1459     return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
1460                                             networkaddr, EPM_PROTOCOL_TCP,
1461                                             endpoint);
1462 }
1463
1464 /**** ncacn_http support ****/
1465
1466 /* 60 seconds is the period native uses */
1467 #define HTTP_IDLE_TIME 60000
1468
1469 /* reference counted to avoid a race between a cancelled call's connection
1470  * being destroyed and the asynchronous InternetReadFileEx call being
1471  * completed */
1472 typedef struct _RpcHttpAsyncData
1473 {
1474     LONG refs;
1475     HANDLE completion_event;
1476     INTERNET_BUFFERSA inet_buffers;
1477     void *destination_buffer; /* the address that inet_buffers.lpvBuffer will be
1478                                * copied into when the call completes */
1479     CRITICAL_SECTION cs;
1480 } RpcHttpAsyncData;
1481
1482 static ULONG RpcHttpAsyncData_AddRef(RpcHttpAsyncData *data)
1483 {
1484     return InterlockedIncrement(&data->refs);
1485 }
1486
1487 static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data)
1488 {
1489     ULONG refs = InterlockedDecrement(&data->refs);
1490     if (!refs)
1491     {
1492         TRACE("destroying async data %p\n", data);
1493         CloseHandle(data->completion_event);
1494         HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer);
1495         DeleteCriticalSection(&data->cs);
1496         HeapFree(GetProcessHeap(), 0, data);
1497     }
1498     return refs;
1499 }
1500
1501 typedef struct _RpcConnection_http
1502 {
1503     RpcConnection common;
1504     HINTERNET app_info;
1505     HINTERNET session;
1506     HINTERNET in_request;
1507     HINTERNET out_request;
1508     HANDLE timer_cancelled;
1509     HANDLE cancel_event;
1510     DWORD last_sent_time;
1511     ULONG bytes_received;
1512     ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */
1513     ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */
1514     UUID connection_uuid;
1515     UUID in_pipe_uuid;
1516     UUID out_pipe_uuid;
1517     RpcHttpAsyncData *async_data;
1518 } RpcConnection_http;
1519
1520 static RpcConnection *rpcrt4_ncacn_http_alloc(void)
1521 {
1522     RpcConnection_http *httpc;
1523     httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc));
1524     if (!httpc) return NULL;
1525     httpc->async_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcHttpAsyncData));
1526     if (!httpc->async_data)
1527     {
1528         HeapFree(GetProcessHeap(), 0, httpc);
1529         return NULL;
1530     }
1531     TRACE("async data = %p\n", httpc->async_data);
1532     httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1533     httpc->async_data->refs = 1;
1534     httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSA);
1535     httpc->async_data->inet_buffers.lpvBuffer = NULL;
1536     httpc->async_data->destination_buffer = NULL;
1537     InitializeCriticalSection(&httpc->async_data->cs);
1538     return &httpc->common;
1539 }
1540
1541 typedef struct _HttpTimerThreadData
1542 {
1543     PVOID timer_param;
1544     DWORD *last_sent_time;
1545     HANDLE timer_cancelled;
1546 } HttpTimerThreadData;
1547
1548 static VOID CALLBACK rpcrt4_http_keep_connection_active_timer_proc(PVOID param, BOOLEAN dummy)
1549 {
1550     HINTERNET in_request = param;
1551     RpcPktHdr *idle_pkt;
1552
1553     idle_pkt = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x0001,
1554                                       0, 0);
1555     if (idle_pkt)
1556     {
1557         DWORD bytes_written;
1558         InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written);
1559         RPCRT4_FreeHeader(idle_pkt);
1560     }
1561 }
1562
1563 static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time)
1564 {
1565     DWORD cur_time = GetTickCount();
1566     DWORD cached_last_sent_time = *last_sent_time;
1567     return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time);
1568 }
1569
1570 static DWORD CALLBACK rpcrt4_http_timer_thread(PVOID param)
1571 {
1572     HttpTimerThreadData *data_in = param;
1573     HttpTimerThreadData data;
1574     DWORD timeout;
1575
1576     data = *data_in;
1577     HeapFree(GetProcessHeap(), 0, data_in);
1578
1579     for (timeout = HTTP_IDLE_TIME;
1580          WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT;
1581          timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time))
1582     {
1583         /* are we too soon after last send? */
1584         if (GetTickCount() - HTTP_IDLE_TIME < *data.last_sent_time)
1585             continue;
1586         rpcrt4_http_keep_connection_active_timer_proc(data.timer_param, TRUE);
1587     }
1588
1589     CloseHandle(data.timer_cancelled);
1590     return 0;
1591 }
1592
1593 static VOID WINAPI rpcrt4_http_internet_callback(
1594      HINTERNET hInternet,
1595      DWORD_PTR dwContext,
1596      DWORD dwInternetStatus,
1597      LPVOID lpvStatusInformation,
1598      DWORD dwStatusInformationLength)
1599 {
1600     RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext;
1601
1602     switch (dwInternetStatus)
1603     {
1604     case INTERNET_STATUS_REQUEST_COMPLETE:
1605         TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n");
1606         if (async_data)
1607         {
1608             if (async_data->inet_buffers.lpvBuffer)
1609             {
1610                 EnterCriticalSection(&async_data->cs);
1611                 if (async_data->destination_buffer)
1612                 {
1613                     memcpy(async_data->destination_buffer,
1614                            async_data->inet_buffers.lpvBuffer,
1615                            async_data->inet_buffers.dwBufferLength);
1616                     async_data->destination_buffer = NULL;
1617                 }
1618                 LeaveCriticalSection(&async_data->cs);
1619             }
1620             HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
1621             async_data->inet_buffers.lpvBuffer = NULL;
1622             SetEvent(async_data->completion_event);
1623             RpcHttpAsyncData_Release(async_data);
1624         }
1625         break;
1626     }
1627 }
1628
1629 static RPC_STATUS rpcrt4_http_check_response(HINTERNET hor)
1630 {
1631     BOOL ret;
1632     DWORD status_code;
1633     DWORD size;
1634     DWORD index;
1635     WCHAR buf[32];
1636     WCHAR *status_text = buf;
1637     TRACE("\n");
1638
1639     index = 0;
1640     size = sizeof(status_code);
1641     ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status_code, &size, &index);
1642     if (!ret)
1643         return GetLastError();
1644     if (status_code < 400)
1645         return RPC_S_OK;
1646     index = 0;
1647     size = sizeof(buf);
1648     ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
1649     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1650     {
1651         status_text = HeapAlloc(GetProcessHeap(), 0, size);
1652         ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
1653     }
1654
1655     ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>");
1656     if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text);
1657
1658     if (status_code == HTTP_STATUS_DENIED)
1659         return ERROR_ACCESS_DENIED;
1660     return RPC_S_SERVER_UNAVAILABLE;
1661 }
1662
1663 static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc)
1664 {
1665     static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0};
1666     LPWSTR proxy = NULL;
1667     LPWSTR user = NULL;
1668     LPWSTR password = NULL;
1669     LPWSTR servername = NULL;
1670     const WCHAR *option;
1671     INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER; /* use default port */
1672
1673     if (httpc->common.QOS &&
1674         (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP))
1675     {
1676         const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials;
1677         if (http_cred->TransportCredentials)
1678         {
1679             WCHAR *p;
1680             const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials;
1681             ULONG len = cred->DomainLength + 1 + cred->UserLength;
1682             user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
1683             if (!user)
1684                 return RPC_S_OUT_OF_RESOURCES;
1685             p = user;
1686             if (cred->DomainLength)
1687             {
1688                 memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR));
1689                 p += cred->DomainLength;
1690                 *p = '\\';
1691                 p++;
1692             }
1693             memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR));
1694             p[cred->UserLength] = 0;
1695
1696             password = RPCRT4_strndupW(cred->Password, cred->PasswordLength);
1697         }
1698     }
1699
1700     for (option = httpc->common.NetworkOptions; option;
1701          option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL))
1702     {
1703         static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0};
1704         static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0};
1705
1706         if (!strncmpiW(option, wszRpcProxy, sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1))
1707         {
1708             const WCHAR *value_start = option + sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1;
1709             const WCHAR *value_end;
1710             const WCHAR *p;
1711
1712             value_end = strchrW(option, ',');
1713             if (!value_end)
1714                 value_end = value_start + strlenW(value_start);
1715             for (p = value_start; p < value_end; p++)
1716                 if (*p == ':')
1717                 {
1718                     port = atoiW(p+1);
1719                     value_end = p;
1720                     break;
1721                 }
1722             TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
1723             servername = RPCRT4_strndupW(value_start, value_end-value_start);
1724         }
1725         else if (!strncmpiW(option, wszHttpProxy, sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1))
1726         {
1727             const WCHAR *value_start = option + sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1;
1728             const WCHAR *value_end;
1729
1730             value_end = strchrW(option, ',');
1731             if (!value_end)
1732                 value_end = value_start + strlenW(value_start);
1733             TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
1734             proxy = RPCRT4_strndupW(value_start, value_end-value_start);
1735         }
1736         else
1737             FIXME("unhandled option %s\n", debugstr_w(option));
1738     }
1739
1740     httpc->app_info = InternetOpenW(wszUserAgent, proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG,
1741                                     NULL, NULL, INTERNET_FLAG_ASYNC);
1742     if (!httpc->app_info)
1743     {
1744         HeapFree(GetProcessHeap(), 0, password);
1745         HeapFree(GetProcessHeap(), 0, user);
1746         ERR("InternetOpenW failed with error %d\n", GetLastError());
1747         return RPC_S_SERVER_UNAVAILABLE;
1748     }
1749     InternetSetStatusCallbackW(httpc->app_info, rpcrt4_http_internet_callback);
1750
1751     /* if no RpcProxy option specified, set the HTTP server address to the
1752      * RPC server address */
1753     if (!servername)
1754     {
1755         servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR));
1756         if (!servername)
1757         {
1758             HeapFree(GetProcessHeap(), 0, password);
1759             HeapFree(GetProcessHeap(), 0, user);
1760             return RPC_S_OUT_OF_RESOURCES;
1761         }
1762         MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1);
1763     }
1764
1765     httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password,
1766                                       INTERNET_SERVICE_HTTP, 0, 0);
1767
1768     HeapFree(GetProcessHeap(), 0, password);
1769     HeapFree(GetProcessHeap(), 0, user);
1770     HeapFree(GetProcessHeap(), 0, servername);
1771
1772     if (!httpc->session)
1773     {
1774         ERR("InternetConnectW failed with error %d\n", GetLastError());
1775         return RPC_S_SERVER_UNAVAILABLE;
1776     }
1777
1778     return RPC_S_OK;
1779 }
1780
1781 /* prepare the in pipe for use by RPC packets */
1782 static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data,
1783                                               const UUID *connection_uuid,
1784                                               const UUID *in_pipe_uuid,
1785                                               const UUID *association_uuid)
1786 {
1787     BYTE packet[44];
1788     BOOL ret;
1789     RPC_STATUS status;
1790     RpcPktHdr *hdr;
1791     INTERNET_BUFFERSW buffers_in;
1792     DWORD bytes_read, bytes_written;
1793
1794     /* prepare in pipe */
1795     ResetEvent(async_data->completion_event);
1796     RpcHttpAsyncData_AddRef(async_data);
1797     ret = HttpSendRequestW(in_request, NULL, 0, NULL, 0);
1798     if (!ret)
1799     {
1800         if (GetLastError() == ERROR_IO_PENDING)
1801             WaitForSingleObject(async_data->completion_event, INFINITE);
1802         else
1803         {
1804             RpcHttpAsyncData_Release(async_data);
1805             ERR("HttpSendRequestW failed with error %d\n", GetLastError());
1806             return RPC_S_SERVER_UNAVAILABLE;
1807         }
1808     }
1809     status = rpcrt4_http_check_response(in_request);
1810     if (status != RPC_S_OK) return status;
1811
1812     InternetReadFile(in_request, packet, 20, &bytes_read);
1813     /* FIXME: do something with retrieved data */
1814
1815     memset(&buffers_in, 0, sizeof(buffers_in));
1816     buffers_in.dwStructSize = sizeof(buffers_in);
1817     /* FIXME: get this from the registry */
1818     buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */
1819     ResetEvent(async_data->completion_event);
1820     RpcHttpAsyncData_AddRef(async_data);
1821     ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0);
1822     if (!ret)
1823     {
1824         if (GetLastError() == ERROR_IO_PENDING)
1825             WaitForSingleObject(async_data->completion_event, INFINITE);
1826         else
1827         {
1828             RpcHttpAsyncData_Release(async_data);
1829             ERR("HttpSendRequestExW failed with error %d\n", GetLastError());
1830             return RPC_S_SERVER_UNAVAILABLE;
1831         }
1832     }
1833
1834     TRACE("sending HTTP connect header to server\n");
1835     hdr = RPCRT4_BuildHttpConnectHeader(0, FALSE, connection_uuid, in_pipe_uuid, association_uuid);
1836     if (!hdr) return RPC_S_OUT_OF_RESOURCES;
1837     ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written);
1838     RPCRT4_FreeHeader(hdr);
1839     if (!ret)
1840     {
1841         ERR("InternetWriteFile failed with error %d\n", GetLastError());
1842         return RPC_S_SERVER_UNAVAILABLE;
1843     }
1844
1845     return RPC_S_OK;
1846 }
1847
1848 static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data)
1849 {
1850     BOOL ret;
1851     DWORD bytes_read;
1852     unsigned short data_len;
1853
1854     ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read);
1855     if (!ret)
1856         return RPC_S_SERVER_UNAVAILABLE;
1857     if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
1858     {
1859         ERR("wrong packet type received %d or wrong frag_len %d\n",
1860             hdr->common.ptype, hdr->common.frag_len);
1861         return RPC_S_PROTOCOL_ERROR;
1862     }
1863
1864     ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read);
1865     if (!ret)
1866         return RPC_S_SERVER_UNAVAILABLE;
1867
1868     data_len = hdr->common.frag_len - sizeof(hdr->http);
1869     if (data_len)
1870     {
1871         *data = HeapAlloc(GetProcessHeap(), 0, data_len);
1872         if (!*data)
1873             return RPC_S_OUT_OF_RESOURCES;
1874         ret = InternetReadFile(request, *data, data_len, &bytes_read);
1875         if (!ret)
1876         {
1877             HeapFree(GetProcessHeap(), 0, *data);
1878             return RPC_S_SERVER_UNAVAILABLE;
1879         }
1880     }
1881     else
1882         *data = NULL;
1883
1884     if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len))
1885     {
1886         ERR("invalid http packet\n");
1887         return RPC_S_PROTOCOL_ERROR;
1888     }
1889
1890     return RPC_S_OK;
1891 }
1892
1893 /* prepare the out pipe for use by RPC packets */
1894 static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request,
1895                                                RpcHttpAsyncData *async_data,
1896                                                const UUID *connection_uuid,
1897                                                const UUID *out_pipe_uuid,
1898                                                ULONG *flow_control_increment)
1899 {
1900     BYTE packet[20];
1901     BOOL ret;
1902     RPC_STATUS status;
1903     RpcPktHdr *hdr;
1904     DWORD bytes_read;
1905     BYTE *data_from_server;
1906     RpcPktHdr pkt_from_server;
1907     ULONG field1, field3;
1908
1909     ResetEvent(async_data->completion_event);
1910     RpcHttpAsyncData_AddRef(async_data);
1911     ret = HttpSendRequestW(out_request, NULL, 0, NULL, 0);
1912     if (!ret)
1913     {
1914         if (GetLastError() == ERROR_IO_PENDING)
1915             WaitForSingleObject(async_data->completion_event, INFINITE);
1916         else
1917         {
1918             RpcHttpAsyncData_Release(async_data);
1919             ERR("HttpSendRequestW failed with error %d\n", GetLastError());
1920             return RPC_S_SERVER_UNAVAILABLE;
1921         }
1922     }
1923     status = rpcrt4_http_check_response(out_request);
1924     if (status != RPC_S_OK) return status;
1925
1926     InternetReadFile(out_request, packet, 20, &bytes_read);
1927     /* FIXME: do something with retrieved data */
1928
1929     hdr = RPCRT4_BuildHttpConnectHeader(0, TRUE, connection_uuid, out_pipe_uuid, NULL);
1930     if (!hdr) return RPC_S_OUT_OF_RESOURCES;
1931     ResetEvent(async_data->completion_event);
1932     RpcHttpAsyncData_AddRef(async_data);
1933     ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len);
1934     if (!ret)
1935     {
1936         if (GetLastError() == ERROR_IO_PENDING)
1937             WaitForSingleObject(async_data->completion_event, INFINITE);
1938         else
1939         {
1940             RpcHttpAsyncData_Release(async_data);
1941             ERR("HttpSendRequestW failed with error %d\n", GetLastError());
1942             RPCRT4_FreeHeader(hdr);
1943             return RPC_S_SERVER_UNAVAILABLE;
1944         }
1945     }
1946     RPCRT4_FreeHeader(hdr);
1947     status = rpcrt4_http_check_response(out_request);
1948     if (status != RPC_S_OK) return status;
1949
1950     status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
1951                                           &data_from_server);
1952     if (status != RPC_S_OK) return status;
1953     status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
1954                                             &field1);
1955     HeapFree(GetProcessHeap(), 0, data_from_server);
1956     if (status != RPC_S_OK) return status;
1957     TRACE("received (%d) from first prepare header\n", field1);
1958
1959     status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
1960                                           &data_from_server);
1961     if (status != RPC_S_OK) return status;
1962     status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server,
1963                                             &field1, flow_control_increment,
1964                                             &field3);
1965     HeapFree(GetProcessHeap(), 0, data_from_server);
1966     if (status != RPC_S_OK) return status;
1967     TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3);
1968
1969     return RPC_S_OK;
1970 }
1971
1972 static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
1973 {
1974     RpcConnection_http *httpc = (RpcConnection_http *)Connection;
1975     static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0};
1976     static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0};
1977     static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0};
1978     static const WCHAR wszColon[] = {':',0};
1979     static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0};
1980     LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL };
1981     WCHAR *url;
1982     RPC_STATUS status;
1983     BOOL secure;
1984     HttpTimerThreadData *timer_data;
1985     HANDLE thread;
1986
1987     TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
1988
1989     if (Connection->server)
1990     {
1991         ERR("ncacn_http servers not supported yet\n");
1992         return RPC_S_SERVER_UNAVAILABLE;
1993     }
1994
1995     if (httpc->in_request)
1996         return RPC_S_OK;
1997
1998     httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1999
2000     status = UuidCreate(&httpc->connection_uuid);
2001     status = UuidCreate(&httpc->in_pipe_uuid);
2002     status = UuidCreate(&httpc->out_pipe_uuid);
2003
2004     status = rpcrt4_http_internet_connect(httpc);
2005     if (status != RPC_S_OK)
2006         return status;
2007
2008     url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR));
2009     if (!url)
2010         return RPC_S_OUT_OF_MEMORY;
2011     memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix));
2012     MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+sizeof(wszRpcProxyPrefix)/sizeof(wszRpcProxyPrefix[0])-1, strlen(Connection->NetworkAddr)+1);
2013     strcatW(url, wszColon);
2014     MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1);
2015
2016     secure = httpc->common.QOS &&
2017              (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) &&
2018              (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL);
2019
2020     httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL,
2021                                          wszAcceptTypes,
2022                                          (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
2023                                          (DWORD_PTR)httpc->async_data);
2024     if (!httpc->in_request)
2025     {
2026         ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2027         return RPC_S_SERVER_UNAVAILABLE;
2028     }
2029     httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL,
2030                                           wszAcceptTypes,
2031                                           (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
2032                                           (DWORD_PTR)httpc->async_data);
2033     if (!httpc->out_request)
2034     {
2035         ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2036         return RPC_S_SERVER_UNAVAILABLE;
2037     }
2038
2039     status = rpcrt4_http_prepare_in_pipe(httpc->in_request,
2040                                          httpc->async_data,
2041                                          &httpc->connection_uuid,
2042                                          &httpc->in_pipe_uuid,
2043                                          &Connection->assoc->http_uuid);
2044     if (status != RPC_S_OK)
2045         return status;
2046
2047     status = rpcrt4_http_prepare_out_pipe(httpc->out_request,
2048                                           httpc->async_data,
2049                                           &httpc->connection_uuid,
2050                                           &httpc->out_pipe_uuid,
2051                                           &httpc->flow_control_increment);
2052     if (status != RPC_S_OK)
2053         return status;
2054
2055     httpc->flow_control_mark = httpc->flow_control_increment / 2;
2056     httpc->last_sent_time = GetTickCount();
2057     httpc->timer_cancelled = CreateEventW(NULL, FALSE, FALSE, NULL);
2058
2059     timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data));
2060     if (!timer_data)
2061         return ERROR_OUTOFMEMORY;
2062     timer_data->timer_param = httpc->in_request;
2063     timer_data->last_sent_time = &httpc->last_sent_time;
2064     timer_data->timer_cancelled = httpc->timer_cancelled;
2065     /* FIXME: should use CreateTimerQueueTimer when implemented */
2066     thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL);
2067     if (!thread)
2068     {
2069         HeapFree(GetProcessHeap(), 0, timer_data);
2070         return GetLastError();
2071     }
2072     CloseHandle(thread);
2073
2074     return RPC_S_OK;
2075 }
2076
2077 static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
2078 {
2079     assert(0);
2080     return RPC_S_SERVER_UNAVAILABLE;
2081 }
2082
2083 static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
2084                                 void *buffer, unsigned int count)
2085 {
2086   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2087   char *buf = buffer;
2088   BOOL ret = TRUE;
2089   unsigned int bytes_left = count;
2090
2091   ResetEvent(httpc->async_data->completion_event);
2092   while (bytes_left)
2093   {
2094     RpcHttpAsyncData_AddRef(httpc->async_data);
2095     httpc->async_data->inet_buffers.dwBufferLength = bytes_left;
2096     httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, bytes_left);
2097     httpc->async_data->destination_buffer = buf;
2098     ret = InternetReadFileExA(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0);
2099     if (ret)
2100     {
2101         /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
2102          * async ref now */
2103         RpcHttpAsyncData_Release(httpc->async_data);
2104         memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer,
2105                httpc->async_data->inet_buffers.dwBufferLength);
2106         HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
2107         httpc->async_data->inet_buffers.lpvBuffer = NULL;
2108         httpc->async_data->destination_buffer = NULL;
2109     }
2110     else
2111     {
2112         if (GetLastError() == ERROR_IO_PENDING)
2113         {
2114             HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
2115             DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
2116             if (result == WAIT_OBJECT_0)
2117                 ret = TRUE;
2118             else
2119             {
2120                 TRACE("call cancelled\n");
2121                 EnterCriticalSection(&httpc->async_data->cs);
2122                 httpc->async_data->destination_buffer = NULL;
2123                 LeaveCriticalSection(&httpc->async_data->cs);
2124                 break;
2125             }
2126         }
2127         else
2128         {
2129             HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
2130             httpc->async_data->inet_buffers.lpvBuffer = NULL;
2131             httpc->async_data->destination_buffer = NULL;
2132             RpcHttpAsyncData_Release(httpc->async_data);
2133             break;
2134         }
2135     }
2136     if (!httpc->async_data->inet_buffers.dwBufferLength)
2137         break;
2138     bytes_left -= httpc->async_data->inet_buffers.dwBufferLength;
2139     buf += httpc->async_data->inet_buffers.dwBufferLength;
2140   }
2141   TRACE("%p %p %u -> %s\n", httpc->out_request, buffer, count, ret ? "TRUE" : "FALSE");
2142   return ret ? count : -1;
2143 }
2144
2145 static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
2146 {
2147   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2148   RPC_STATUS status;
2149   DWORD hdr_length;
2150   LONG dwRead;
2151   RpcPktCommonHdr common_hdr;
2152
2153   *Header = NULL;
2154
2155   TRACE("(%p, %p, %p)\n", Connection, Header, Payload);
2156
2157 again:
2158   /* read packet common header */
2159   dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr));
2160   if (dwRead != sizeof(common_hdr)) {
2161     WARN("Short read of header, %d bytes\n", dwRead);
2162     status = RPC_S_PROTOCOL_ERROR;
2163     goto fail;
2164   }
2165   if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) ||
2166       !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0")))
2167   {
2168     FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr));
2169     status = RPC_S_PROTOCOL_ERROR;
2170     goto fail;
2171   }
2172
2173   status = RPCRT4_ValidateCommonHeader(&common_hdr);
2174   if (status != RPC_S_OK) goto fail;
2175
2176   hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
2177   if (hdr_length == 0) {
2178     WARN("header length == 0\n");
2179     status = RPC_S_PROTOCOL_ERROR;
2180     goto fail;
2181   }
2182
2183   *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);
2184   if (!*Header)
2185   {
2186     status = RPC_S_OUT_OF_RESOURCES;
2187     goto fail;
2188   }
2189   memcpy(*Header, &common_hdr, sizeof(common_hdr));
2190
2191   /* read the rest of packet header */
2192   dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr));
2193   if (dwRead != hdr_length - sizeof(common_hdr)) {
2194     WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length);
2195     status = RPC_S_PROTOCOL_ERROR;
2196     goto fail;
2197   }
2198
2199   if (common_hdr.frag_len - hdr_length)
2200   {
2201     *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length);
2202     if (!*Payload)
2203     {
2204       status = RPC_S_OUT_OF_RESOURCES;
2205       goto fail;
2206     }
2207
2208     dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length);
2209     if (dwRead != common_hdr.frag_len - hdr_length)
2210     {
2211       WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length);
2212       status = RPC_S_PROTOCOL_ERROR;
2213       goto fail;
2214     }
2215   }
2216   else
2217     *Payload = NULL;
2218
2219   if ((*Header)->common.ptype == PKT_HTTP)
2220   {
2221     if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length))
2222     {
2223       ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len);
2224       status = RPC_S_PROTOCOL_ERROR;
2225       goto fail;
2226     }
2227     if ((*Header)->http.flags == 0x0001)
2228     {
2229       TRACE("http idle packet, waiting for real packet\n");
2230       if ((*Header)->http.num_data_items != 0)
2231       {
2232         ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items);
2233         status = RPC_S_PROTOCOL_ERROR;
2234         goto fail;
2235       }
2236     }
2237     else if ((*Header)->http.flags == 0x0002)
2238     {
2239       ULONG bytes_transmitted;
2240       ULONG flow_control_increment;
2241       UUID pipe_uuid;
2242       status = RPCRT4_ParseHttpFlowControlHeader(*Header, *Payload,
2243                                                  Connection->server,
2244                                                  &bytes_transmitted,
2245                                                  &flow_control_increment,
2246                                                  &pipe_uuid);
2247       if (status != RPC_S_OK)
2248         goto fail;
2249       TRACE("received http flow control header (0x%x, 0x%x, %s)\n",
2250             bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid));
2251       /* FIXME: do something with parsed data */
2252     }
2253     else
2254     {
2255       FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags);
2256       status = RPC_S_PROTOCOL_ERROR;
2257       goto fail;
2258     }
2259     RPCRT4_FreeHeader(*Header);
2260     *Header = NULL;
2261     HeapFree(GetProcessHeap(), 0, *Payload);
2262     *Payload = NULL;
2263     goto again;
2264   }
2265
2266   /* success */
2267   status = RPC_S_OK;
2268
2269   httpc->bytes_received += common_hdr.frag_len;
2270
2271   TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received);
2272
2273   if (httpc->bytes_received > httpc->flow_control_mark)
2274   {
2275     RpcPktHdr *hdr = RPCRT4_BuildHttpFlowControlHeader(httpc->common.server,
2276                                                        httpc->bytes_received,
2277                                                        httpc->flow_control_increment,
2278                                                        &httpc->out_pipe_uuid);
2279     if (hdr)
2280     {
2281       DWORD bytes_written;
2282       BOOL ret2;
2283       TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received);
2284       ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written);
2285       RPCRT4_FreeHeader(hdr);
2286       if (ret2)
2287         httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2;
2288     }
2289   }
2290
2291 fail:
2292   if (status != RPC_S_OK) {
2293     RPCRT4_FreeHeader(*Header);
2294     *Header = NULL;
2295     HeapFree(GetProcessHeap(), 0, *Payload);
2296     *Payload = NULL;
2297   }
2298   return status;
2299 }
2300
2301 static int rpcrt4_ncacn_http_write(RpcConnection *Connection,
2302                                  const void *buffer, unsigned int count)
2303 {
2304   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2305   DWORD bytes_written;
2306   BOOL ret;
2307
2308   httpc->last_sent_time = ~0UL; /* disable idle packet sending */
2309   ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written);
2310   httpc->last_sent_time = GetTickCount();
2311   TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE");
2312   return ret ? bytes_written : -1;
2313 }
2314
2315 static int rpcrt4_ncacn_http_close(RpcConnection *Connection)
2316 {
2317   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2318
2319   TRACE("\n");
2320
2321   SetEvent(httpc->timer_cancelled);
2322   if (httpc->in_request)
2323     InternetCloseHandle(httpc->in_request);
2324   httpc->in_request = NULL;
2325   if (httpc->out_request)
2326     InternetCloseHandle(httpc->out_request);
2327   httpc->out_request = NULL;
2328   if (httpc->app_info)
2329     InternetCloseHandle(httpc->app_info);
2330   httpc->app_info = NULL;
2331   if (httpc->session)
2332     InternetCloseHandle(httpc->session);
2333   httpc->session = NULL;
2334   RpcHttpAsyncData_Release(httpc->async_data);
2335   if (httpc->cancel_event)
2336     CloseHandle(httpc->cancel_event);
2337
2338   return 0;
2339 }
2340
2341 static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection)
2342 {
2343   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2344
2345   SetEvent(httpc->cancel_event);
2346 }
2347
2348 static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection)
2349 {
2350   BOOL ret;
2351   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2352
2353   RpcHttpAsyncData_AddRef(httpc->async_data);
2354   ret = InternetQueryDataAvailable(httpc->out_request,
2355     &httpc->async_data->inet_buffers.dwBufferLength, IRF_ASYNC, 0);
2356   if (ret)
2357   {
2358       /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
2359        * async ref now */
2360       RpcHttpAsyncData_Release(httpc->async_data);
2361   }
2362   else
2363   {
2364     if (GetLastError() == ERROR_IO_PENDING)
2365     {
2366       HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
2367       DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
2368       if (result != WAIT_OBJECT_0)
2369       {
2370         TRACE("call cancelled\n");
2371         return -1;
2372       }
2373     }
2374     else
2375     {
2376       RpcHttpAsyncData_Release(httpc->async_data);
2377       return -1;
2378     }
2379   }
2380
2381   /* success */
2382   return 0;
2383 }
2384
2385 static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data,
2386                                                  const char *networkaddr,
2387                                                  const char *endpoint)
2388 {
2389     return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
2390                                           EPM_PROTOCOL_HTTP, endpoint);
2391 }
2392
2393 static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data,
2394                                                        size_t tower_size,
2395                                                        char **networkaddr,
2396                                                        char **endpoint)
2397 {
2398     return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
2399                                             networkaddr, EPM_PROTOCOL_HTTP,
2400                                             endpoint);
2401 }
2402 #endif  /* HAVE_SOCKETPAIR */
2403
2404 static const struct connection_ops conn_protseq_list[] = {
2405   { "ncacn_np",
2406     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
2407     rpcrt4_conn_np_alloc,
2408     rpcrt4_ncacn_np_open,
2409     rpcrt4_ncacn_np_handoff,
2410     rpcrt4_conn_np_read,
2411     rpcrt4_conn_np_write,
2412     rpcrt4_conn_np_close,
2413     rpcrt4_conn_np_cancel_call,
2414     rpcrt4_conn_np_wait_for_incoming_data,
2415     rpcrt4_ncacn_np_get_top_of_tower,
2416     rpcrt4_ncacn_np_parse_top_of_tower,
2417     NULL,
2418   },
2419   { "ncalrpc",
2420     { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
2421     rpcrt4_conn_np_alloc,
2422     rpcrt4_ncalrpc_open,
2423     rpcrt4_ncalrpc_handoff,
2424     rpcrt4_conn_np_read,
2425     rpcrt4_conn_np_write,
2426     rpcrt4_conn_np_close,
2427     rpcrt4_conn_np_cancel_call,
2428     rpcrt4_conn_np_wait_for_incoming_data,
2429     rpcrt4_ncalrpc_get_top_of_tower,
2430     rpcrt4_ncalrpc_parse_top_of_tower,
2431     NULL,
2432   },
2433 #ifdef HAVE_SOCKETPAIR
2434   { "ncacn_ip_tcp",
2435     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
2436     rpcrt4_conn_tcp_alloc,
2437     rpcrt4_ncacn_ip_tcp_open,
2438     rpcrt4_conn_tcp_handoff,
2439     rpcrt4_conn_tcp_read,
2440     rpcrt4_conn_tcp_write,
2441     rpcrt4_conn_tcp_close,
2442     rpcrt4_conn_tcp_cancel_call,
2443     rpcrt4_conn_tcp_wait_for_incoming_data,
2444     rpcrt4_ncacn_ip_tcp_get_top_of_tower,
2445     rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
2446     NULL,
2447   },
2448   { "ncacn_http",
2449     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP },
2450     rpcrt4_ncacn_http_alloc,
2451     rpcrt4_ncacn_http_open,
2452     rpcrt4_ncacn_http_handoff,
2453     rpcrt4_ncacn_http_read,
2454     rpcrt4_ncacn_http_write,
2455     rpcrt4_ncacn_http_close,
2456     rpcrt4_ncacn_http_cancel_call,
2457     rpcrt4_ncacn_http_wait_for_incoming_data,
2458     rpcrt4_ncacn_http_get_top_of_tower,
2459     rpcrt4_ncacn_http_parse_top_of_tower,
2460     rpcrt4_ncacn_http_receive_fragment,
2461   },
2462 #endif
2463 };
2464
2465
2466 static const struct protseq_ops protseq_list[] =
2467 {
2468     {
2469         "ncacn_np",
2470         rpcrt4_protseq_np_alloc,
2471         rpcrt4_protseq_np_signal_state_changed,
2472         rpcrt4_protseq_np_get_wait_array,
2473         rpcrt4_protseq_np_free_wait_array,
2474         rpcrt4_protseq_np_wait_for_new_connection,
2475         rpcrt4_protseq_ncacn_np_open_endpoint,
2476     },
2477     {
2478         "ncalrpc",
2479         rpcrt4_protseq_np_alloc,
2480         rpcrt4_protseq_np_signal_state_changed,
2481         rpcrt4_protseq_np_get_wait_array,
2482         rpcrt4_protseq_np_free_wait_array,
2483         rpcrt4_protseq_np_wait_for_new_connection,
2484         rpcrt4_protseq_ncalrpc_open_endpoint,
2485     },
2486 #ifdef HAVE_SOCKETPAIR
2487     {
2488         "ncacn_ip_tcp",
2489         rpcrt4_protseq_sock_alloc,
2490         rpcrt4_protseq_sock_signal_state_changed,
2491         rpcrt4_protseq_sock_get_wait_array,
2492         rpcrt4_protseq_sock_free_wait_array,
2493         rpcrt4_protseq_sock_wait_for_new_connection,
2494         rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
2495     },
2496 #endif
2497 };
2498
2499 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
2500
2501 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
2502 {
2503   unsigned int i;
2504   for(i=0; i<ARRAYSIZE(protseq_list); i++)
2505     if (!strcmp(protseq_list[i].name, protseq))
2506       return &protseq_list[i];
2507   return NULL;
2508 }
2509
2510 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
2511 {
2512     unsigned int i;
2513     for(i=0; i<ARRAYSIZE(conn_protseq_list); i++)
2514         if (!strcmp(conn_protseq_list[i].name, protseq))
2515             return &conn_protseq_list[i];
2516     return NULL;
2517 }
2518
2519 /**** interface to rest of code ****/
2520
2521 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection)
2522 {
2523   TRACE("(Connection == ^%p)\n", Connection);
2524
2525   assert(!Connection->server);
2526   return Connection->ops->open_connection_client(Connection);
2527 }
2528
2529 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
2530 {
2531   TRACE("(Connection == ^%p)\n", Connection);
2532   if (SecIsValidHandle(&Connection->ctx))
2533   {
2534     DeleteSecurityContext(&Connection->ctx);
2535     SecInvalidateHandle(&Connection->ctx);
2536   }
2537   rpcrt4_conn_close(Connection);
2538   return RPC_S_OK;
2539 }
2540
2541 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
2542     LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
2543     LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
2544 {
2545   const struct connection_ops *ops;
2546   RpcConnection* NewConnection;
2547
2548   ops = rpcrt4_get_conn_protseq_ops(Protseq);
2549   if (!ops)
2550   {
2551     FIXME("not supported for protseq %s\n", Protseq);
2552     return RPC_S_PROTSEQ_NOT_SUPPORTED;
2553   }
2554
2555   NewConnection = ops->alloc();
2556   NewConnection->Next = NULL;
2557   NewConnection->server_binding = NULL;
2558   NewConnection->server = server;
2559   NewConnection->ops = ops;
2560   NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
2561   NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
2562   NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
2563   NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
2564   memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface));
2565   NewConnection->NextCallId = 1;
2566
2567   SecInvalidateHandle(&NewConnection->ctx);
2568   memset(&NewConnection->exp, 0, sizeof(NewConnection->exp));
2569   NewConnection->attr = 0;
2570   if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
2571   NewConnection->AuthInfo = AuthInfo;
2572   NewConnection->encryption_auth_len = 0;
2573   NewConnection->signature_auth_len = 0;
2574   if (QOS) RpcQualityOfService_AddRef(QOS);
2575   NewConnection->QOS = QOS;
2576
2577   list_init(&NewConnection->conn_pool_entry);
2578   NewConnection->async_state = NULL;
2579
2580   TRACE("connection: %p\n", NewConnection);
2581   *Connection = NewConnection;
2582
2583   return RPC_S_OK;
2584 }
2585
2586 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
2587 {
2588   RPC_STATUS err;
2589
2590   err = RPCRT4_CreateConnection(Connection, OldConnection->server,
2591                                 rpcrt4_conn_get_name(OldConnection),
2592                                 OldConnection->NetworkAddr,
2593                                 OldConnection->Endpoint, NULL,
2594                                 OldConnection->AuthInfo, OldConnection->QOS);
2595   if (err == RPC_S_OK)
2596     rpcrt4_conn_handoff(OldConnection, *Connection);
2597   return err;
2598 }
2599
2600 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
2601 {
2602   TRACE("connection: %p\n", Connection);
2603
2604   RPCRT4_CloseConnection(Connection);
2605   RPCRT4_strfree(Connection->Endpoint);
2606   RPCRT4_strfree(Connection->NetworkAddr);
2607   HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
2608   if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
2609   if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
2610
2611   /* server-only */
2612   if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
2613
2614   HeapFree(GetProcessHeap(), 0, Connection);
2615   return RPC_S_OK;
2616 }
2617
2618 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
2619                                       size_t *tower_size,
2620                                       const char *protseq,
2621                                       const char *networkaddr,
2622                                       const char *endpoint)
2623 {
2624     twr_empty_floor_t *protocol_floor;
2625     const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
2626
2627     *tower_size = 0;
2628
2629     if (!protseq_ops)
2630         return RPC_S_INVALID_RPC_PROTSEQ;
2631
2632     if (!tower_data)
2633     {
2634         *tower_size = sizeof(*protocol_floor);
2635         *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
2636         return RPC_S_OK;
2637     }
2638
2639     protocol_floor = (twr_empty_floor_t *)tower_data;
2640     protocol_floor->count_lhs = sizeof(protocol_floor->protid);
2641     protocol_floor->protid = protseq_ops->epm_protocols[0];
2642     protocol_floor->count_rhs = 0;
2643
2644     tower_data += sizeof(*protocol_floor);
2645
2646     *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
2647     if (!*tower_size)
2648         return EPT_S_NOT_REGISTERED;
2649
2650     *tower_size += sizeof(*protocol_floor);
2651
2652     return RPC_S_OK;
2653 }
2654
2655 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
2656                                         size_t tower_size,
2657                                         char **protseq,
2658                                         char **networkaddr,
2659                                         char **endpoint)
2660 {
2661     const twr_empty_floor_t *protocol_floor;
2662     const twr_empty_floor_t *floor4;
2663     const struct connection_ops *protseq_ops = NULL;
2664     RPC_STATUS status;
2665     unsigned int i;
2666
2667     if (tower_size < sizeof(*protocol_floor))
2668         return EPT_S_NOT_REGISTERED;
2669
2670     protocol_floor = (const twr_empty_floor_t *)tower_data;
2671     tower_data += sizeof(*protocol_floor);
2672     tower_size -= sizeof(*protocol_floor);
2673     if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
2674         (protocol_floor->count_rhs > tower_size))
2675         return EPT_S_NOT_REGISTERED;
2676     tower_data += protocol_floor->count_rhs;
2677     tower_size -= protocol_floor->count_rhs;
2678
2679     floor4 = (const twr_empty_floor_t *)tower_data;
2680     if ((tower_size < sizeof(*floor4)) ||
2681         (floor4->count_lhs != sizeof(floor4->protid)))
2682         return EPT_S_NOT_REGISTERED;
2683
2684     for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++)
2685         if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
2686             (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
2687         {
2688             protseq_ops = &conn_protseq_list[i];
2689             break;
2690         }
2691
2692     if (!protseq_ops)
2693         return EPT_S_NOT_REGISTERED;
2694
2695     status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
2696
2697     if ((status == RPC_S_OK) && protseq)
2698     {
2699         *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
2700         strcpy(*protseq, protseq_ops->name);
2701     }
2702
2703     return status;
2704 }
2705
2706 /***********************************************************************
2707  *             RpcNetworkIsProtseqValidW (RPCRT4.@)
2708  *
2709  * Checks if the given protocol sequence is known by the RPC system.
2710  * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
2711  *
2712  */
2713 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq)
2714 {
2715   char ps[0x10];
2716
2717   WideCharToMultiByte(CP_ACP, 0, protseq, -1,
2718                       ps, sizeof ps, NULL, NULL);
2719   if (rpcrt4_get_conn_protseq_ops(ps))
2720     return RPC_S_OK;
2721
2722   FIXME("Unknown protseq %s\n", debugstr_w(protseq));
2723
2724   return RPC_S_INVALID_RPC_PROTSEQ;
2725 }
2726
2727 /***********************************************************************
2728  *             RpcNetworkIsProtseqValidA (RPCRT4.@)
2729  */
2730 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq)
2731 {
2732   UNICODE_STRING protseqW;
2733
2734   if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
2735   {
2736     RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
2737     RtlFreeUnicodeString(&protseqW);
2738     return ret;
2739   }
2740   return RPC_S_OUT_OF_MEMORY;
2741 }