source: abuse/trunk/src/net/netfile.cpp @ 555

Last change on this file since 555 was 555, checked in by Sam Hocevar, 10 years ago

ps3: make everything compile on the PS3. Of course, nothing links yet
because so much support is missing.

File size: 11.9 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include "common.h"
16
17#include "netfile.h"
18#include "../inc/netface.h"
19#include "engine.h"
20
21
22nfs_client *first_nfs_client=NULL;
23remote_file *remote_file_list=NULL;
24char default_fs_name[256];    // default file server name (set with parm -fs)
25
26nfs_client::nfs_client(net_socket *sock, int file_fd, nfs_client *next) :
27  sock(sock),file_fd(file_fd),next(next),size_to_read(0)
28{
29  sock->read_selectable();
30}
31
32
33nfs_client::~nfs_client()
34{
35  delete sock;
36  if (file_fd>=0)
37    close(file_fd);
38}
39
40void secure_filename(char *filename, char *mode)
41{
42  if (!no_security)
43  {
44    if (filename[0]=='/') { filename[0]=0; return ; }
45    int level=0;
46    char *f=filename;
47    while (*f)
48    {
49      if (*f=='/') { f++; level++; }
50      else if (*f=='.' && f[1]=='.')
51      {
52    if (f[3]=='.') while (*f!='.') f++;
53    else
54    {
55      f+=2;
56      level--;
57    }
58      } else f++;
59
60    }
61    if (level<0)
62      filename[0]=0;
63  }
64}
65
66
67int local_address(char *server_name)    // returns 1 if server name is ourself
68{
69  struct hostent *hn=gethostbyname(server_name);    // first check to see if this address is 127.0.0.1
70  if (!hn) return 0;                                // if bad server_name, return false
71  char **ip_address=hn->h_addr_list;
72  while (*ip_address)
73  {
74    char *a=*ip_address;
75    if (a[0]==127 && a[1]==0 && a[2]==0 && a[3]==1)
76      return 1;
77    ip_address++;
78  }
79  char server_ip[4];
80  memcpy(server_ip,hn->h_addr_list,4);
81
82  char my_name[100];                              // now check to see if this address is 'hostname'
83  gethostname(my_name,100);
84  struct hostent *l_hn=gethostbyname(my_name);
85  char **l_ip_address=l_hn->h_addr_list;
86
87  while (*l_ip_address)  // local ip_address
88  {
89    char *a=*l_ip_address;         // scan through all local ip's
90    ip_address=hn->h_addr_list;
91    while (*ip_address)            // scan through all ip's for server_name
92    {
93      char *b=server_ip;
94      if (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3])    // check for match
95        return 1;
96      ip_address++;
97    }
98    l_ip_address++;
99  }
100  return 0;       // didn't match localhost nor hostname, must be somewhere else
101}
102
103int nfs_client::send_read()   // return 0 if failure on socket, not failure to read
104{
105  if (file_fd>=0 && socket_fd>=0)
106  {
107    // first make sure the socket isn't 'full'
108
109    struct timeval tv={ 0,0};     // don't wait
110    fd_set write_check;
111    FD_ZERO(&write_check);
112    FD_SET(socket_fd,&write_check);
113    select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
114
115    if (FD_ISSET(socket_fd,&write_check))            // ready to write?
116    {
117      char buf[READ_PACKET_SIZE];
118      int16_t read_total;
119      int16_t actual;
120
121      do
122      {
123    read_total=size_to_read>(READ_PACKET_SIZE-2) ? (READ_PACKET_SIZE-2) : size_to_read;
124    actual=read(file_fd,buf,read_total);
125    actual=lstl(actual);
126    if (write(socket_fd,&actual,sizeof(actual))!=sizeof(actual))
127    {
128      fprintf(stderr,"write failed\n");
129      return 0;
130    }
131    actual=lstl(actual);
132
133    int write_amount=write(socket_fd,buf,actual);
134    if (write_amount!=actual)
135    {
136      fprintf(stderr,"write failed\n");
137      return 0;
138    }
139
140    size_to_read-=actual;
141
142    FD_ZERO(&write_check);
143    FD_SET(socket_fd,&write_check);
144    select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
145
146    if (!FD_ISSET(socket_fd,&write_check))
147    {
148      FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
149      FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
150      return 1;    // not ok to write anymore, try again latter
151    }
152
153      } while (size_to_read && actual==read_total);
154      size_to_read=0;
155      FD_CLR(socket_fd,&master_write_set);       // don't check this socket for write ok
156      FD_SET(socket_fd,&master_set);             // check it for reading
157      return 1;
158    } else
159    {
160      FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
161      FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
162      return 1;
163    }
164  }
165  return 0;
166}
167
168
169int process_nfs_command(nfs_client *c)
170{
171  char cmd;
172  if (read(c->socket_fd,&cmd,1)!=1) return 0;
173  switch (cmd)
174  {
175    case NFCMD_READ :
176    {
177      int32_t size;
178      if (read(c->socket_fd,&size,sizeof(size))!=sizeof(size)) return 0;
179      size=lltl(size);
180
181      c->size_to_read=size;
182      return c->send_read();
183    } break;
184    case NFCMD_CLOSE :
185    {
186      return 0;
187    } break;
188    case NFCMD_SEEK :
189    {
190      int32_t offset;
191      if (read(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
192      offset=lltl(offset);
193      offset=lseek(c->file_fd,offset,0);
194      offset=lltl(offset);
195      if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
196      return 1;
197    } break;
198    case NFCMD_TELL :
199    {
200      int32_t offset=lseek(c->file_fd,0,SEEK_CUR);
201      offset=lltl(offset);
202      if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
203      return 1;
204    } break;
205
206    default :
207    { fprintf(stderr,"net driver : bad command from nfs client\n");
208      return 0;
209    }
210  }
211}
212
213
214
215void add_nfs_client(int fd)
216{
217  uint8_t size[2];
218  char filename[300],mode[20],*mp;
219  if (read(fd,size,2)!=2) { close(fd); return ; }
220  if (read(fd,filename,size[0])!=size[0]) { close(fd); return ; }
221  if (read(fd,mode,size[1])!=size[1]) { close(fd); return ; }
222
223  fprintf(stderr,"remote request for %s ",filename);
224
225  secure_filename(filename,mode);  // make sure this filename isn't a security risk
226  if (filename[0]==0) { fprintf(stderr,"(denied)\n"); close(fd); return ; }
227
228  mp=mode;
229  int flags=0;
230
231  while (*mp)
232  {
233    if (*mp=='w') flags|=O_CREAT|O_RDWR;
234    else if (*mp=='r') flags|=O_RDONLY;
235    mp++;
236  }
237
238  int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
239
240  if (f<0)
241  {
242    fprintf(stderr,"(not found)\n");
243    f=-1;  // make sure this is -1
244  }
245
246  int32_t ret=lltl(f);
247  if (write(fd,&ret,sizeof(ret))!=sizeof(ret)) { close(fd); return ; }
248
249  if (f<0)    // no file, sorry
250    close(fd);
251  else
252  {
253    int32_t cur_pos=lseek(f,0,SEEK_CUR);
254    int32_t size=lseek(f,0,SEEK_END);
255    lseek(f,cur_pos,SEEK_SET);
256    size=lltl(size);
257    if (write(fd,&size,sizeof(size))!=sizeof(size)) {  close(f); close(fd); return ; }
258
259    first_nfs_client=new nfs_client(fd,f,first_nfs_client);
260    first_nfs_client->size=size;
261  }
262}
263
264void remote_file::r_close(char *reason)
265{
266  if (reason)
267    fprintf(stderr,"remote_file : %s\n",reason);
268  if (socket_fd>=0)
269  {
270    uint8_t cmd=NFCMD_CLOSE;
271    write(socket_fd,&cmd,1);
272    close(socket_fd);
273  }
274  socket_fd=-1;
275}
276
277remote_file::remote_file(char *filename, char *mode, remote_file *Next)
278{
279  next=Next;
280  open_local=0;
281
282  socket_fd=connect_to_server(filename);
283  if (socket_fd==-1)
284  {
285    fprintf(stderr,"unable to connect\n");
286    return ;
287  }
288
289  uint8_t sizes[3]={ CLIENT_NFS,strlen(filename)+1,strlen(mode)+1};
290  if (write(socket_fd,sizes,3)!=3) { r_close("could not send open info"); return ; }
291  if (write(socket_fd,filename,sizes[1])!=sizes[1]) { r_close("could not send filename"); return ; }
292  if (write(socket_fd,mode,sizes[2])!=sizes[2]) { r_close("could not send mode"); return ; }
293
294  int32_t remote_file_fd;
295  if (read(socket_fd,&remote_file_fd,sizeof(remote_file_fd))!=sizeof(remote_file_fd))
296  { r_close("could not read remote fd"); return ; }
297  remote_file_fd=lltl(remote_file_fd);
298  if (remote_file_fd<0) { r_close("remote fd is bad"); return ; }
299
300  if (read(socket_fd,&size,sizeof(size))!=sizeof(size)) { r_close("could not read remote filesize"); return ; }
301//  uint32_t remote_crc;
302//  if (read(socket_fd,&remote_crc,sizeof(remote_crc))!=sizeof(remote_crc)) { r_close("could not read remote checksum"); return ; }
303//  uint32_t local_crc=
304
305  size=lltl(size);
306}
307
308int remote_file::unbuffered_read(int out_fd, size_t count)
309{
310  if (socket_fd>=0 && count)
311  {
312    uint8_t cmd=NFCMD_READ;
313    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("read : could not send command"); return 0; }
314
315    int32_t rsize=lltl(count);
316    if (write(socket_fd,&rsize,sizeof(rsize))!=sizeof(rsize)) { r_close("read : could not send size"); return 0; }
317
318    int32_t total_read=0,total;
319    char buf[READ_PACKET_SIZE];
320    uint16_t size;
321
322    uint16_t packet_size;
323    do
324    {
325      if (read(socket_fd,&packet_size,sizeof(packet_size))!=sizeof(packet_size))
326      {
327    fprintf(stderr,"could not read packet size\n");
328    return 0;
329      }
330      packet_size=lstl(packet_size);
331
332      uint16_t size_read=read(socket_fd,buf+2,packet_size);
333
334      if (size_read!=packet_size)
335      {
336    if (read(socket_fd,buf+2+size_read,packet_size-size_read)!=packet_size-size_read)
337    {
338      fprintf(stderr,"incomplete packet\n");
339      return 0;
340    }
341      }
342
343      *((int16_t *)buf)=packet_size;
344      if (write(out_fd,buf,packet_size+2)!=packet_size+2) comm_failed();
345
346      total_read+=packet_size;
347      count-=packet_size;
348    } while (packet_size==READ_PACKET_SIZE-2 && count);
349    return total_read;
350  }
351  return 0;
352}
353
354int remote_file::unbuffered_tell()   // ask server where the offset of the file pointer is
355{
356  if (socket_fd>=0)
357  {
358    uint8_t cmd=NFCMD_TELL;
359    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("tell : could not send command"); return 0; }
360
361    int32_t offset;
362    if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("tell : could not read offset"); return 0; }
363    return lltl(offset);
364  }
365  return 0;
366}
367
368int remote_file::unbuffered_seek(int32_t offset)  // tell server to seek to a spot in a file
369{
370  if (socket_fd>=0)
371  {
372    uint8_t cmd=NFCMD_SEEK;
373    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("seek : could not send command"); return 0; }
374
375    int32_t off=lltl(offset);
376    if (write(socket_fd,&off,sizeof(off))!=sizeof(off)) { r_close("seek : could not send offset"); return 0; }
377
378    if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("seek : could not read offset"); return 0; }
379    return lltl(offset);
380  }
381  return 0;
382}
383
384int open_file(char *&filename, char *mode)
385{
386  if (filename[0]!='/' && filename[1]!='/' && default_fs_name[0])   // default file server?
387  {
388    char tmp_fn[500];
389    sprintf(tmp_fn,"//%s/%s",default_fs_name,filename);
390    strcpy(filename,tmp_fn);
391  }
392
393  if (filename[0]=='/' && filename[1]=='/')   // passive server file reference?
394  {
395    filename+=2;
396    remote_file *rf=new remote_file(filename,mode,remote_file_list);
397    if (rf->open_failure())
398    {
399      delete rf;
400      return -1;
401    }
402    else
403    {
404      remote_file_list=rf;
405      return rf->socket_fd;
406    }
407  }
408
409  secure_filename(filename,mode);
410  if (filename[0]==0) return -1;
411
412  int flags=0;
413  while (*mode)
414  {
415    if (*mode=='w') flags|=O_CREAT|O_RDWR;
416    else if (*mode=='r') flags|=O_RDONLY;
417    mode++;
418  }
419
420  int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
421  if (f>=0)
422  { close(f);
423    return -2;
424  }
425
426  return -1;
427}
428
429remote_file *find_rfile(int fd)
430{
431  remote_file *r=remote_file_list;
432  for (; r && r->socket_fd!=fd; r=r->next)
433  {
434    if (r->socket_fd==-1)
435    {
436      fprintf(stderr,"bad sock\n");
437    }
438  }
439  return r;
440}
441
442void unlink_remote_file(remote_file *rf)
443{
444  if (rf==remote_file_list)
445    remote_file_list=rf->next;
446  else
447  {
448    remote_file *last=remote_file_list;
449    while (last->next && last->next!=rf) last=last->next;
450    last->next=rf->next;
451  }
452}
453
454remote_file::~remote_file()
455{ r_close(NULL); }
456
457
458int fetch_crcs(char *server)
459{
460  int socket_fd=connect_to_server(server);
461  if (socket_fd==-1)
462  {
463    fprintf(stderr,"unable to connect\n");
464    return 0;
465  }
466
467  uint8_t cmd=CLIENT_CRC_WAITER;
468  if (write(socket_fd,&cmd,1)!=1)  { close(socket_fd); return 0; }
469  if (read(socket_fd,&cmd,1)!=1)  { close(socket_fd); return 0; }
470  close(socket_fd);
471  return cmd;
472
473}
474
475
Note: See TracBrowser for help on using the repository browser.