Subversion Repositories Spectranet

Compare Revisions

Rev 556 → Rev 570

/tnfs-protocol.txt
349,11 → 349,16
Reads a block of data from a file. Consists of the standard header
followed by the file descriptor as returned by OPEN, then a 16 bit
little endian integer specifying the size of data that is requested.
 
The server will only reply with as much data as fits in the maximum
TNFS datagram size of 1K. If there is less than the size requested
remaining in the file, the server will return the remainder of the file.
Subsequent READ commands will return the code EOF.
TNFS datagram size of 1K when using UDP as a transport. For the
TCP transport, sequencing and buffering etc. are just left up to
the TCP stack, so a READ operation can return blocks of up to 64K.
 
If there is less than the size requested remaining in the file,
the server will return the remainder of the file. Subsequent READ
commands will return the code EOF.
 
Examples:
Read from fd 4, maximum 256 bytes:
 
/tnfsd/config.h
26,7 → 26,8
#define MAXMSGSZ 532 /* maximum size of a TNFS message */
#define MAX_FD_PER_CONN 16 /* maximum open file descriptors per client */
#define MAX_DHND_PER_CONN 8 /* max open directories per client */
#define MAX_CLIENTS 256 /* maximum number of clients */
#define MAX_CLIENTS 256 /* maximum number of UDP clients */
#define MAX_TCP_CONN 256 /* Maximum number of TCP clients */
#define TNFS_HEADERSZ 4 /* minimum header size */
#define MAX_TNFSPATH 256 /* maximum path length */
#define MAX_FILEPATH 384 /* Maximum path + filename */
/tnfsd/tnfs.h
83,6 → 83,7
unsigned char lastmsg[MAXMSGSZ];/* last message sent */
int lastmsgsz; /* last message's size inc. hdr */
uint8_t lastseqno; /* last sequence number */
uint8_t isTCP; /* uses the TCP transport */
 
} Session;
 
/tnfsd/datagram.c
32,6 → 32,7
#ifdef UNIX
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#endif
 
#ifdef WIN32
47,7 → 48,8
#include "directory.h"
#include "tnfs_file.h"
 
int sockfd; /* global socket file descriptor */
int sockfd; /* UDP global socket file descriptor */
int tcplistenfd; /* TCP listening socket file descriptor */
 
tnfs_cmdfunc dircmd[NUM_DIRCMDS]=
{ &tnfs_opendir, &tnfs_readdir, &tnfs_closedir,
67,6 → 69,7
die("WSAStartup() failed");
#endif
 
/* Create the UDP socket */
sockfd=socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0)
die("Unable to open socket");
79,34 → 82,130
if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
die("Unable to bind");
 
/* Create the TCP socket */
tcplistenfd=socket(AF_INET, SOCK_STREAM, 0);
if(tcplistenfd < 0) {
die("Unable to create TCP socket");
}
 
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htons(INADDR_ANY);
servaddr.sin_port=htons(TNFSD_PORT);
if (bind(tcplistenfd, (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0) {
die("Unable to bind TCP socket");
}
listen(tcplistenfd, 5);
}
 
void tnfs_mainloop()
{
{
int readyfds, i;
fd_set fdset;
fd_set errfdset;
int tcpsocks[MAX_TCP_CONN];
 
memset(&tcpsocks, 0, sizeof(tcpsocks));
while(1) {
FD_ZERO(&fdset);
 
/* add UDP socket and TCP listen socket to fdset */
FD_SET(sockfd, &fdset);
FD_SET(tcplistenfd, &fdset);
 
for(i=0; i<MAX_TCP_CONN; i++) {
if(tcpsocks[i]) {
FD_SET(tcpsocks[i], &fdset);
}
}
FD_COPY(&fdset, &errfdset);
if((readyfds=select
(FD_SETSIZE, &fdset, NULL, &errfdset, NULL)) != 0) {
if(readyfds < 0) {
die("select() failed\n");
}
 
/* handle fds ready for reading */
/* UDP message? */
if(FD_ISSET(sockfd, &fdset)) {
tnfs_handle_udpmsg();
}
/* Incoming TCP connection? */
else if(FD_ISSET(tcplistenfd, &fdset)) {
tcp_accept(&tcpsocks[0]);
}
 
else {
for(i=0; i<MAX_TCP_CONN; i++) {
if(tcpsocks[i]) {
if(FD_ISSET(tcpsocks[i],&fdset))
{
tnfs_handle_tcpmsg(tcpsocks[i]);
}
}
}
}
}
}
}
 
void tcp_accept(int *socklist) {
int acc_fd, i;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
int *fdptr;
 
acc_fd=accept(tcplistenfd, (struct sockaddr *) &cli_addr, &cli_len);
if(acc_fd < 1) {
fprintf(stderr, "WARNING: unable to accept TCP connection\n");
return;
}
 
fdptr=socklist;
for(i=0; i<MAX_TCP_CONN; i++) {
if(*fdptr == 0) {
*fdptr=acc_fd;
return;
}
}
 
/* tell the client 'too many connections' */
}
 
void tnfs_handle_udpmsg() {
socklen_t len;
int rxbytes;
struct sockaddr_in cliaddr;
unsigned char rxbuf[MAXMSGSZ];
 
while(1)
len=sizeof(cliaddr);
rxbytes=recvfrom(sockfd, rxbuf, sizeof(rxbuf), 0,
(struct sockaddr *)&cliaddr, &len);
 
if(rxbytes >= TNFS_HEADERSZ)
{
len=sizeof(cliaddr);
rxbytes=recvfrom(sockfd, rxbuf, sizeof(rxbuf), 0,
(struct sockaddr *)&cliaddr, &len);
/* probably a valid TNFS packet, decode it */
tnfs_decode(&cliaddr, rxbytes, rxbuf);
}
else
{
MSGLOG(cliaddr.sin_addr.s_addr,
"Invalid datagram received");
}
 
if(rxbytes >= TNFS_HEADERSZ)
{
/* probably a valid TNFS packet, decode it */
tnfs_decode(&cliaddr, rxbytes, rxbuf);
}
else
{
MSGLOG(cliaddr.sin_addr.s_addr,
"Invalid datagram received");
}
*(rxbuf+rxbytes)=0;
}
 
*(rxbuf+rxbytes)=0;
}
void tnfs_handle_tcpmsg(int cli_fd) {
char buf[255];
int sz;
 
sz=read(cli_fd, buf, sizeof(buf));
printf("DEBUG: rx of tcpmsg: %d bytes: %s\n", sz, buf);
}
 
void tnfs_decode(struct sockaddr_in *cliaddr, int rxbytes, unsigned char *rxbuf)
/tnfsd/datagram.h
44,6 → 44,9
/* Handle the socket interface */
void tnfs_sockinit();
void tnfs_mainloop();
void tnfs_handle_udpmsg();
void tcp_accept(int *fdlist);
void tnfs_handle_tcpmsg(int cli_fd);
void tnfs_decode(struct sockaddr_in *cliaddr,
int rxbytes, unsigned char *rxbuf);
void tnfs_badcommand(Header *hdr, Session *sess);