2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
11 #include <sys/socket.h>
21 /***********************************************************************
22 * CLIENT_SendRequest_v
24 * Send a request to the server.
26 static void CLIENT_SendRequest_v( enum request req
, int pass_fd
,
27 struct iovec
*vec
, int veclen
)
29 THDB
*thdb
= THREAD_Current();
30 struct { struct cmsghdr hdr
; int fd
; } cmsg
=
31 { { sizeof(cmsg
), SOL_SOCKET
, SCM_RIGHTS
}, pass_fd
};
36 msghdr
.msg_name
= NULL
;
37 msghdr
.msg_namelen
= 0;
41 vec
[0].iov_base
= &head
;
42 vec
[0].iov_len
= sizeof(head
);
44 msghdr
.msg_iovlen
= veclen
;
45 for (i
= len
= 0; i
< veclen
; i
++) len
+= vec
[i
].iov_len
;
47 assert( len
<= MAX_MSG_LENGTH
);
50 head
.seq
= thdb
->seq
++;
52 if (pass_fd
== -1) /* no fd to pass */
54 msghdr
.msg_control
= NULL
;
55 msghdr
.msg_controllen
= 0;
59 msghdr
.msg_control
= &cmsg
;
60 msghdr
.msg_controllen
= sizeof(cmsg
);
63 if ((ret
= sendmsg( thdb
->socket
, &msghdr
, 0 )) < len
)
65 fprintf( stderr
, "Fatal protocol error: " );
66 if (ret
== -1) perror( "sendmsg" );
67 else fprintf( stderr
, "partial msg sent %d/%d\n", ret
, len
);
70 /* we passed the fd now we can close it */
71 if (pass_fd
!= -1) close( pass_fd
);
75 /***********************************************************************
78 * Send a request to the server.
80 static void CLIENT_SendRequest( enum request req
, int pass_fd
,
81 int n
, ... /* arg_1, len_1, etc. */ )
90 for (i
= 1; i
< n
; i
++)
92 vec
[i
].iov_base
= va_arg( args
, void * );
93 vec
[i
].iov_len
= va_arg( args
, int );
96 return CLIENT_SendRequest_v( req
, pass_fd
, vec
, n
);
100 /***********************************************************************
103 * Wait for a reply from the server.
104 * Returns the error code (or 0 if OK).
106 static unsigned int CLIENT_WaitReply_v( int *len
, int *passed_fd
,
107 struct iovec
*vec
, int veclen
)
109 THDB
*thdb
= THREAD_Current();
110 struct { struct cmsghdr hdr
; int fd
; } cmsg
=
111 { { sizeof(cmsg
), SOL_SOCKET
, SCM_RIGHTS
}, -1 };
112 struct msghdr msghdr
;
116 assert( veclen
> 0 );
117 vec
[0].iov_base
= &head
;
118 vec
[0].iov_len
= sizeof(head
);
119 msghdr
.msg_name
= NULL
;
120 msghdr
.msg_namelen
= 0;
121 msghdr
.msg_iov
= vec
;
122 msghdr
.msg_iovlen
= veclen
;
123 msghdr
.msg_control
= &cmsg
;
124 msghdr
.msg_controllen
= sizeof(cmsg
);
126 if ((ret
= recvmsg( thdb
->socket
, &msghdr
, 0 )) == -1)
128 fprintf( stderr
, "Fatal protocol error: " );
132 if (ret
< sizeof(head
))
135 "Fatal protocol error: partial header received %d/%d\n",
139 if ((head
.len
< sizeof(head
)) || (head
.len
> MAX_MSG_LENGTH
))
141 fprintf( stderr
, "Fatal protocol error: header length %d\n",
145 if (head
.seq
!= thdb
->seq
++)
148 "Fatal protocol error: sequence %08x instead of %08x\n",
149 head
.seq
, thdb
->seq
- 1 );
153 if (head
.type
!= ERROR_SUCCESS
)
155 SetLastError( head
.type
);
159 *passed_fd
= cmsg
.fd
;
163 if (len
) *len
= ret
- sizeof(head
);
164 if (cmsg
.fd
!= -1) close( cmsg
.fd
);
165 remaining
= head
.len
- ret
;
166 while (remaining
> 0) /* drop remaining data */
169 int len
= remaining
< sizeof(buffer
) ? remaining
: sizeof(buffer
);
170 if ((len
= recv( thdb
->socket
, buffer
, len
, 0 )) == -1)
172 fprintf( stderr
, "Fatal protocol error: " );
179 return head
.type
; /* error code */
183 /***********************************************************************
186 * Wait for a reply from the server.
188 static unsigned int CLIENT_WaitReply( int *len
, int *passed_fd
,
189 int n
, ... /* arg_1, len_1, etc. */ )
191 struct iovec vec
[16];
195 n
++; /* for vec[0] */
198 for (i
= 1; i
< n
; i
++)
200 vec
[i
].iov_base
= va_arg( args
, void * );
201 vec
[i
].iov_len
= va_arg( args
, int );
204 return CLIENT_WaitReply_v( len
, passed_fd
, vec
, n
);
208 /***********************************************************************
211 * Send a new thread request. Helper function for CLIENT_NewThread.
213 static int send_new_thread( THDB
*thdb
)
215 struct new_thread_request request
;
216 struct new_thread_reply reply
;
219 if (socketpair( AF_UNIX
, SOCK_STREAM
, PF_UNIX
, fd
) == -1)
221 SetLastError( ERROR_TOO_MANY_OPEN_FILES
); /* FIXME */
225 request
.pid
= thdb
->process
->server_pid
;
226 CLIENT_SendRequest( REQ_NEW_THREAD
, fd
[1], 1, &request
, sizeof(request
) );
228 if (CLIENT_WaitReply( &len
, NULL
, 1, &reply
, sizeof(reply
) )) goto error
;
229 if (len
< sizeof(reply
)) goto error
;
230 thdb
->server_tid
= reply
.tid
;
231 thdb
->process
->server_pid
= reply
.pid
;
232 if (thdb
->socket
!= -1) close( thdb
->socket
);
233 thdb
->socket
= fd
[0];
234 thdb
->seq
= 0; /* reset the sequence number for the new fd */
243 /***********************************************************************
246 * Send a new thread request.
248 int CLIENT_NewThread( THDB
*thdb
)
250 extern BOOL32 THREAD_InitDone
;
252 if (!THREAD_InitDone
) /* first thread -> start the server */
257 if (socketpair( AF_UNIX
, SOCK_STREAM
, PF_UNIX
, tmpfd
) == -1)
259 perror("socketpair");
269 sprintf( buffer
, "%d", tmpfd
[1] );
271 execlp( "wineserver", "wineserver", buffer
, NULL
);
272 execl( "/usr/local/bin/wineserver", "wineserver", buffer
, NULL
);
273 execl( "./server/wineserver", "wineserver", buffer
, NULL
);
275 server_main_loop( tmpfd
[1] );
277 default: /* parent */
279 SET_CUR_THREAD( thdb
);
280 THREAD_InitDone
= TRUE
;
281 thdb
->socket
= tmpfd
[0];
286 return send_new_thread( thdb
);
290 /***********************************************************************
293 * Send an init thread request. Return 0 if OK.
295 int CLIENT_InitThread(void)
297 THDB
*thdb
= THREAD_Current();
298 struct init_thread_request init
;
299 int len
= strlen( thdb
->process
->env_db
->cmd_line
);
302 len
= MIN( len
, MAX_MSG_LENGTH
- sizeof(init
) );
304 CLIENT_SendRequest( REQ_INIT_THREAD
, -1, 2,
306 thdb
->process
->env_db
->cmd_line
, len
);
307 return CLIENT_WaitReply( NULL
, NULL
, NULL
, 0 );