VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/filenet.c@ 24107

Last change on this file since 24107 was 18328, checked in by vboxsync, 16 years ago

crOpenGL: init mutexes as recursive, fix for #3758

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.3 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <fcntl.h>
10#include <sys/stat.h>
11#ifdef WINDOWS
12#include <io.h>
13#else
14#include <unistd.h>
15#endif
16
17
18#include "cr_error.h"
19#include "cr_mem.h"
20#include "cr_string.h"
21#include "cr_bufpool.h"
22#include "cr_net.h"
23#include "cr_endian.h"
24#include "cr_threads.h"
25#include "net_internals.h"
26
27typedef enum {
28 CRFileMemory,
29 CRFileMemoryBig
30} CRFileBufferKind;
31
32#define CR_FILE_BUFFER_MAGIC 0x89134539
33
34#ifndef WINDOWS
35#define O_BINARY 0
36#endif
37
38typedef struct CRFileBuffer {
39 unsigned int magic;
40 CRFileBufferKind kind;
41 unsigned int len;
42 unsigned int allocated;
43 unsigned int pad;
44} CRFileBuffer;
45
46static struct {
47 int initialized;
48 int num_conns;
49 CRConnection **conns;
50 CRBufferPool *bufpool;
51#ifdef CHROMIUM_THREADSAFE
52 CRmutex mutex;
53#endif
54 CRNetReceiveFuncList *recv_list;
55 CRNetCloseFuncList *close_list;
56} cr_file;
57
58static void
59crFileReadExact( CRConnection *conn, void *buf, unsigned int len )
60{
61 char *dst = (char *) buf;
62
63 while ( len > 0 )
64 {
65 int num_read = read( conn->fd, buf, len );
66
67 if ( num_read < 0 )
68 {
69 crError( "Bad bad bad file error!" );
70 }
71 if (num_read == 0)
72 {
73 crError( "END OF FILE!" );
74 }
75
76 dst += num_read;
77 len -= num_read;
78 }
79}
80
81static void
82crFileWriteExact( CRConnection *conn, const void *buf, unsigned int len )
83{
84 int retval = write( conn->fd, buf, len );
85 if ( retval < (int) len )
86 {
87 crError( "crFileWriteExact: %s (tried to write %d bytes, actually wrote %d)", conn->filename, len, retval );
88 }
89}
90
91static void
92crFileAccept( CRConnection *conn, const char *hostname, unsigned short port )
93{
94 conn->file_direction = CR_FILE_READ;
95 conn->fd = open( conn->filename, O_RDONLY | O_BINARY );
96 if (conn->fd < 0)
97 {
98 crError( "Couldn't open %s for reading!", conn->filename );
99 }
100 (void) port;
101}
102
103static void
104*crFileAlloc( CRConnection *conn )
105{
106 CRFileBuffer *buf;
107
108#ifdef CHROMIUM_THREADSAFE
109 crLockMutex(&cr_file.mutex);
110#endif
111
112 buf = (CRFileBuffer *) crBufferPoolPop( cr_file.bufpool, conn->buffer_size );
113
114 if ( buf == NULL )
115 {
116 crDebug( "Buffer pool was empty, so I allocated %d bytes",
117 (int)(sizeof(CRFileBuffer) + conn->buffer_size) );
118 buf = (CRFileBuffer *)
119 crAlloc( sizeof(CRFileBuffer) + conn->buffer_size );
120 buf->magic = CR_FILE_BUFFER_MAGIC;
121 buf->kind = CRFileMemory;
122 buf->pad = 0;
123 buf->allocated = conn->buffer_size;
124 }
125
126#ifdef CHROMIUM_THREADSAFE
127 crUnlockMutex(&cr_file.mutex);
128#endif
129
130 return (void *)( buf + 1 );
131}
132
133static void
134crFileSingleRecv( CRConnection *conn, void *buf, unsigned int len )
135{
136 crFileReadExact( conn, buf, len );
137}
138
139static void
140crFileSend( CRConnection *conn, void **bufp, const void *start, unsigned int len )
141{
142 CRFileBuffer *file_buffer;
143 unsigned int *lenp;
144
145 if ( bufp == NULL )
146 {
147 /* we are doing synchronous sends from user memory, so no need
148 * to get fancy. Simply write the length & the payload and
149 * return. */
150 if (conn->swap)
151 {
152 len = SWAP32(len);
153 }
154 crFileWriteExact( conn, &len, sizeof(len) );
155 crFileWriteExact( conn, start, len );
156 return;
157 }
158
159 file_buffer = (CRFileBuffer *)(*bufp) - 1;
160
161 CRASSERT( file_buffer->magic == CR_FILE_BUFFER_MAGIC );
162
163 /* All of the buffers passed to the send function were allocated
164 * with crFileAlloc(), which includes a header with a 4 byte
165 * length field, to insure that we always have a place to write
166 * the length field, even when start == *bufp. */
167 lenp = (unsigned int *) start - 1;
168 *lenp = len;
169
170 crFileWriteExact(conn, lenp, len + sizeof(int) );
171
172 /* reclaim this pointer for reuse and try to keep the client from
173 accidentally reusing it directly */
174#ifdef CHROMIUM_THREADSAFE
175 crLockMutex(&cr_file.mutex);
176#endif
177 crBufferPoolPush( cr_file.bufpool, file_buffer, conn->buffer_size );
178#ifdef CHROMIUM_THREADSAFE
179 crUnlockMutex(&cr_file.mutex);
180#endif
181 *bufp = NULL;
182}
183
184static void
185crFileFree( CRConnection *conn, void *buf )
186{
187 CRFileBuffer *file_buffer = (CRFileBuffer *) buf - 1;
188
189 CRASSERT( file_buffer->magic == CR_FILE_BUFFER_MAGIC );
190 conn->recv_credits += file_buffer->len;
191
192 switch ( file_buffer->kind )
193 {
194 case CRFileMemory:
195#ifdef CHROMIUM_THREADSAFE
196 crLockMutex(&cr_file.mutex);
197#endif
198 crBufferPoolPush( cr_file.bufpool, file_buffer, conn->buffer_size );
199#ifdef CHROMIUM_THREADSAFE
200 crUnlockMutex(&cr_file.mutex);
201#endif
202 break;
203
204 case CRFileMemoryBig:
205 crFree( file_buffer );
206 break;
207
208 default:
209 crError( "Weird buffer kind trying to free in crFileFree: %d", file_buffer->kind );
210 }
211}
212
213int
214crFileRecv( void )
215{
216 CRMessage *msg;
217 int i;
218
219 if (!cr_file.num_conns)
220 {
221 return 0;
222 }
223 for ( i = 0; i < cr_file.num_conns; i++ )
224 {
225 CRFileBuffer *file_buffer;
226 unsigned int len;
227 CRConnection *conn = cr_file.conns[i];
228
229 crFileReadExact( conn, &len, sizeof( len ) );
230
231 CRASSERT( len > 0 );
232
233 if ( len <= conn->buffer_size )
234 {
235 file_buffer = (CRFileBuffer *) crFileAlloc( conn ) - 1;
236 }
237 else
238 {
239 file_buffer = (CRFileBuffer *)
240 crAlloc( sizeof(*file_buffer) + len );
241 file_buffer->magic = CR_FILE_BUFFER_MAGIC;
242 file_buffer->kind = CRFileMemoryBig;
243 file_buffer->pad = 0;
244 }
245
246 file_buffer->len = len;
247
248 crFileReadExact( conn, file_buffer + 1, len );
249
250 conn->recv_credits -= len;
251
252 msg = (CRMessage *) (file_buffer + 1);
253 crNetDispatchMessage( cr_file.recv_list, conn, msg, len );
254
255 /* CR_MESSAGE_OPCODES is freed in
256 * crserverlib/server_stream.c
257 *
258 * OOB messages are the programmer's problem. -- Humper 12/17/01 */
259 if (msg->header.type != CR_MESSAGE_OPCODES && msg->header.type != CR_MESSAGE_OOB)
260 {
261 crFileFree( conn, file_buffer + 1 );
262 }
263 }
264
265 return 1;
266}
267
268static void
269crFileHandleNewMessage( CRConnection *conn, CRMessage *msg,
270 unsigned int len )
271{
272 CRFileBuffer *buf = ((CRFileBuffer *) msg) - 1;
273
274 /* build a header so we can delete the message later */
275 buf->magic = CR_FILE_BUFFER_MAGIC;
276 buf->kind = CRFileMemory;
277 buf->len = len;
278 buf->pad = 0;
279
280 crNetDispatchMessage( cr_file.recv_list, conn, msg, len );
281}
282
283static void
284crFileInstantReclaim( CRConnection *conn, CRMessage *mess )
285{
286 crFileFree( conn, mess );
287}
288
289void
290crFileInit( CRNetReceiveFuncList *rfl, CRNetCloseFuncList *cfl, unsigned int mtu )
291{
292 (void) mtu;
293
294 cr_file.recv_list = rfl;
295 cr_file.close_list = cfl;
296
297 if (cr_file.initialized)
298 {
299 return;
300 }
301
302 cr_file.num_conns = 0;
303 cr_file.conns = NULL;
304
305#ifdef CHROMIUM_THREADSAFE
306 crInitMutex(&cr_file.mutex);
307#endif
308 cr_file.bufpool = crBufferPoolInit(16);
309
310
311 cr_file.initialized = 1;
312}
313
314static int
315crFileDoConnect( CRConnection *conn )
316{
317 conn->file_direction = CR_FILE_WRITE;
318 /* NOTE: the third parameter (file permissions) is only used/required when
319 * we specify O_CREAT as part of the flags. The permissions will be
320 * masked according to the effective user's umask setting.
321 */
322#ifdef WINDOWS
323 conn->fd = open( conn->filename, O_CREAT | O_WRONLY | O_BINARY |
324 S_IREAD | S_IWRITE);
325#else
326 conn->fd = open( conn->filename, O_CREAT | O_WRONLY | O_BINARY,
327 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
328#endif
329 if (conn->fd < 0)
330 {
331 crWarning( "Couldn't open %s for writing!", conn->filename );
332 return 0;
333 }
334 return 1;
335}
336
337static void
338crFileDoDisconnect( CRConnection *conn )
339{
340 close( conn->fd );
341 conn->type = CR_NO_CONNECTION;
342 crMemcpy( cr_file.conns + conn->index, cr_file.conns + conn->index+1,
343 (cr_file.num_conns - conn->index - 1)*sizeof(*(cr_file.conns)) );
344 cr_file.num_conns--;
345}
346
347void
348crFileConnection( CRConnection *conn )
349{
350 int n_bytes;
351
352 CRASSERT( cr_file.initialized );
353
354 conn->type = CR_FILE;
355 conn->Alloc = crFileAlloc;
356 conn->Send = crFileSend;
357 conn->SendExact = crFileWriteExact;
358 conn->Recv = crFileSingleRecv;
359 conn->Free = crFileFree;
360 conn->Accept = crFileAccept;
361 conn->Connect = crFileDoConnect;
362 conn->Disconnect = crFileDoDisconnect;
363 conn->InstantReclaim = crFileInstantReclaim;
364 conn->HandleNewMessage = crFileHandleNewMessage;
365 conn->index = cr_file.num_conns;
366 conn->sizeof_buffer_header = sizeof( CRFileBuffer );
367 conn->actual_network = 0;
368
369 conn->filename = crStrdup( conn->hostname );
370
371 n_bytes = ( cr_file.num_conns + 1 ) * sizeof(*cr_file.conns);
372 crRealloc( (void **) &cr_file.conns, n_bytes );
373
374 cr_file.conns[cr_file.num_conns++] = conn;
375}
376
377CRConnection**
378crFileDump( int* num )
379{
380 *num = cr_file.num_conns;
381
382 return cr_file.conns;
383}
384
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette