⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileserverstdio.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
字号:
///////////////////////////////////////////////////////////////
// 
// STDIO_FS
//
// STDIO Device Driver using host\FILESERVER over TCP/IP to
// implement the file actions (fopen(), fread(), etc).
//
///////////////////////////////////////////////////////////////

#include <device.h>
#include <ccblkfn.h>
#include <cdefBF533.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <device_int.h>

#define LWIP_COMPAT_SOCKETS 1
#define SOCKET_ERROR -1
#include <lwip\sockets.h>
#include <lwip\inet.h>

static int   FS_init  (struct DevEntry *dev);
static int   FS_open  (const char *name, int mode);
static int   FS_close (int fd);
static int   FS_write (int fd, unsigned char *buf, int size);
static int   FS_read  (int fd, unsigned char *buf, int size);
static long   FS_seek  (int fd, long offset, int whence);

static DevEntry FS_DevEntry =
{
	0,
	NULL,
	FS_init,
	FS_open,
	FS_close,
	FS_write,
	FS_read,
	FS_seek,
	dev_not_claimed,
	dev_not_claimed,
	dev_not_claimed
};

static char stdout_buf[512];
static char stderr_buf[512];

#define MAX_CONNECTIONS 8

typedef struct _ctt {
    const char*        fileName;
    int                openMode;
    int                socket_fd;
    struct sockaddr_in srv;
    struct sockaddr_in clt;
} connect_t;

typedef struct _skt {
    const char* serverIP;
    const char* clientIP;
    short       serverPort;
    short       nextClientPort;
    connect_t   connections[MAX_CONNECTIONS];
} sock_tab_t;

static sock_tab_t sock_tab;

//
// accept one of stdin, stdout and stderr and reopen it as "con:" which is
// a special filename known to the file server
//
static int redirect(FILE* std)
{
    FILE* fp;
    
    fp = freopen("con:", "a+", std);
    if (!fp) {
        fprintf(stderr, "ERROR: failed to redirect '%s'\n",
               (std == stdin)? "stdin" : (std == stdout)? "stdout" : "stderr");
        return -1;
    }
    return 0;
}

//
// create a connection to file server and request that file be opened
//
static int make_connection(const char* name, int mode, int cndx)
{
    connect_t* cp = &sock_tab.connections[cndx];
    
    cp->fileName = name;
    cp->openMode = mode;
    cp->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (cp->socket_fd < 0)
        return -1;
    
    
    cp->srv.sin_family = AF_INET;
    cp->srv.sin_addr.s_addr = inet_addr(sock_tab.serverIP);
    cp->srv.sin_port = htons(sock_tab.serverPort);
    if (connect(cp->socket_fd, (struct sockaddr*)&cp->srv,
                sizeof(struct sockaddr_in)) == -1) {
        close(cp->socket_fd);
        memset(cp, 0, sizeof(connect_t));
        return -1;
    }

    // malloc enough space for the open request
    int len = 4 + 4 + strlen(name) + 1;
    int* bp = (int*)malloc(len);
    
    if (!bp)
        return -1;
    bp[0] = len - 4;
    bp[1] = mode;
    strcpy((char*)&bp[2], name);
    
    if (FS_write(cndx, (unsigned char*)bp, len) == -1) {
        close(cp->socket_fd);
        memset(cp, 0, sizeof(connect_t));
        free(bp);
        return -1;
    }
    
    free(bp);
    
    return 0;
}


//
// initialisation function for this STDIO device driver
//
// accepts an application-unique device number which it uses to install
// an entry into the runtime's device table; it then makes this driver the
// default one and redirects the standard files
//
// the other arguments identify the network IP address and port of the 
// file server machine and the IP address of this machine; the clientPortBase
// argument is the base of a set of 16 port addresses that this driver may use
// for its connections
//
int FS_STDIO_init(int         devID,
                  const char* serverIPaddr,
                  short       serverPort)
{
    // initialise the socket table
    memset((void*)&sock_tab, 0, sizeof(sock_tab));
    
    sock_tab.serverIP       = serverIPaddr;
    sock_tab.serverPort     = serverPort;
    
    // insert this ethernet-based fileserver client into the runtime's 
    // device table
    FS_DevEntry.DeviceID = devID;
    FS_DevEntry.data = (void*)0;
    int dev = add_devtab_entry(&FS_DevEntry);
    if (dev != devID) {
        fprintf(stderr, "ERROR: Unable to register new STDIO device\n");
        return -1;
    }
    
    // make it the default STDIO device
    set_default_io_device(devID);

    // freopen special filename "con:" as stdout and stderr
    //if (redirect(stdin))  return -2;
    if (redirect(stdout)) return -3;
    if (redirect(stderr)) return -4;
    
    // ensure stdout and stderr are line-buffered
    setvbuf(stdout, stdout_buf, _IOFBF, sizeof(stdout_buf));
    setvbuf(stderr, stderr_buf, _IOFBF, sizeof(stderr_buf));

    return 0;
}    

//
// called when this driver is inserted into the runtime's device table
//
static int   FS_init  ( struct DevEntry *dev )
{
    // just report the redirection using current STDIO
    printf("STDIO being redirected to file server on port %d of host %s\n",
           sock_tab.serverPort, sock_tab.serverIP);
           
	return 0;
}

//
// called when app does an fopen()
//
// allocate an entry in sock_tab, obtain a socket connection to the
// file server running elsewhere on the network and send it an 'open'
// request; return the index of the sock_tab entry (which the runtime
// then uses as the 'fid' parameter to FS_Read, FS_Write, etc)
//
static int   FS_open  (const char *name, int mode)
{
    // if filename is "con:" map directly to connection number 0; make
    // the connection if not already present
    if (!strcmp(name, "con:")) {
        if (sock_tab.connections[0].fileName == 0) {
            if (make_connection(name, mode, 0) == -1)
                return -1;
        }
        return 0;
    }
    
    // if not "con:" allocate a free socket table entry and make connection
    int i;
    
    for (i = 1; i < MAX_CONNECTIONS; i += 1) {
        if (sock_tab.connections[i].fileName == 0) 
            break;
    }
    if (i == MAX_CONNECTIONS)
        return -1;

    if (make_connection(name, mode, i) == -1)
        return -1;
    
    // return connection table index
	return i;
}

static int   FS_write (int fd, unsigned char *buf, int size)
{
    // ensure fd indexes a valid socket table entry
    if (fd < 0 || fd >= MAX_CONNECTIONS)
        return -1;

    // write 'buf' directly to the socket
    int num_written = 0;
    do {
        int r = write(sock_tab.connections[fd].socket_fd,
                      (void*)(buf + num_written),
                      size - num_written);
        if (r == -1)
            return -1;
            
        num_written += r;
    } while (num_written < size);
    
	return num_written;
}

static int   FS_read  (int fd, unsigned char *buf, int size)
{
    // ensure fd indexes a valid socket table entry
    if (fd < 0 || fd >= MAX_CONNECTIONS)
        return -1;
        
    // read from socket directly into 'buf'
    int r = read(sock_tab.connections[fd].socket_fd, (void*)buf, size);
    
    // return number of bytes actually read, or failure	
	return r;
}

static long   FS_seek  (int fd, long offset, int whence)
{
    // return failure
	return -1;
}

static int   FS_close (int fd)
{
    // ensure fd indexes a valid socket table entry
    if (fd < 0 || fd >= MAX_CONNECTIONS)
        return -1;
        
    // close socket
    int r = close(sock_tab.connections[fd].socket_fd);
    
    memset((void*)&sock_tab.connections[fd], 0, sizeof(connect_t));
    
	return r;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -