OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc1/] [or1ksim/] [peripheral/] [channels/] [tcp.c] - Diff between revs 1572 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1572 Rev 1765
/* tcp.c -- Definition of functions for peripheral to
/* tcp.c -- Definition of functions for peripheral to
 * communicate with host via a tcp socket.
 * communicate with host via a tcp socket.
 
 
   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
This file is part of OpenRISC 1000 Architectural Simulator.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
 
 
#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <fcntl.h>
#include <errno.h>
#include <errno.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <unistd.h>
#include <unistd.h>
 
 
#include "channel.h"
#include "channel.h"
#include "generic.h"
#include "generic.h"
#include "fd.h"
#include "fd.h"
 
 
struct tcp_channel
struct tcp_channel
{
{
        struct fd_channel fds;
        struct fd_channel fds;
        int socket_fd;                          /* Socket to listen to */
        int socket_fd;                          /* Socket to listen to */
        int port_number;                        /* TCP port number */
        int port_number;                        /* TCP port number */
        int connected;                          /* If 0, no remote endpoint yet */
        int connected;                          /* If 0, no remote endpoint yet */
        int nonblocking;                        /* If 0, read/write will block until
        int nonblocking;                        /* If 0, read/write will block until
                                                                   remote client connects */
                                                                   remote client connects */
};
};
 
 
static void * tcp_init(const char * input)
static void * tcp_init(const char * input)
{
{
        int port_number, fd, flags;
        int port_number, fd, flags;
        struct sockaddr_in local_ip;
        struct sockaddr_in local_ip;
        struct tcp_channel* channel = (struct tcp_channel*)malloc(sizeof(struct tcp_channel));
        struct tcp_channel* channel = (struct tcp_channel*)malloc(sizeof(struct tcp_channel));
        if (!channel)
        if (!channel)
                return NULL;
                return NULL;
 
 
        fd = 0;
        fd = 0;
        channel->nonblocking = 1;
        channel->nonblocking = 1;
        channel->fds.fdin = -1;
        channel->fds.fdin = -1;
        channel->fds.fdout = -1;
        channel->fds.fdout = -1;
        channel->socket_fd = -1;
        channel->socket_fd = -1;
        channel->port_number = -1;
        channel->port_number = -1;
 
 
        port_number = atoi(input);
        port_number = atoi(input);
        if (port_number == 0)
        if (port_number == 0)
                goto error;
                goto error;
 
 
        fd = socket(AF_INET, SOCK_STREAM, 0);
        fd = socket(AF_INET, SOCK_STREAM, 0);
        if (fd < 0)
        if (fd < 0)
                goto error;
                goto error;
 
 
        flags = 1;
        flags = 1;
        if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0)
        if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0)
    {
    {
                perror("Can not set SO_REUSEADDR option on channel socket");
                perror("Can not set SO_REUSEADDR option on channel socket");
                goto error;
                goto error;
        }
        }
 
 
        memset(&local_ip, 0, sizeof(local_ip));
        memset(&local_ip, 0, sizeof(local_ip));
        local_ip.sin_family = AF_INET;
        local_ip.sin_family = AF_INET;
        local_ip.sin_addr.s_addr = htonl(INADDR_ANY);
        local_ip.sin_addr.s_addr = htonl(INADDR_ANY);
        local_ip.sin_port = htons(port_number);
        local_ip.sin_port = htons(port_number);
        if (bind(fd, (struct sockaddr*)&local_ip, sizeof(local_ip)) < 0) {
        if (bind(fd, (struct sockaddr*)&local_ip, sizeof(local_ip)) < 0) {
                perror("Can't bind local address");
                perror("Can't bind local address");
                goto error;
                goto error;
        }
        }
 
 
        if (channel->nonblocking) {
        if (channel->nonblocking) {
                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                {
                {
                        perror("Can not make channel socket non-blocking");
                        perror("Can not make channel socket non-blocking");
                        goto error;
                        goto error;
                }
                }
        }
        }
 
 
        if (listen(fd, 1) < 0)
        if (listen(fd, 1) < 0)
                goto error;
                goto error;
 
 
        channel->socket_fd = fd;
        channel->socket_fd = fd;
        channel->port_number = port_number;
        channel->port_number = port_number;
        channel->connected = 0;
        channel->connected = 0;
        return (void*)channel;
        return (void*)channel;
 
 
error:
error:
        if (fd)
        if (fd)
                close(fd);
                close(fd);
        free(channel);
        free(channel);
        return NULL;
        return NULL;
}
}
 
 
static int tcp_open(void * data)
static int tcp_open(void * data)
{
{
        /* Socket is opened lazily, upon first read or write, so do nothing here */
        /* Socket is opened lazily, upon first read or write, so do nothing here */
        return 0;
        return 0;
}
}
 
 
 
 
static int wait_for_tcp_connect(struct tcp_channel* channel)
static int wait_for_tcp_connect(struct tcp_channel* channel)
{
{
        int fd;
        int fd;
        socklen_t sizeof_remote_ip;
        socklen_t sizeof_remote_ip;
        struct sockaddr_in remote_ip;
        struct sockaddr_in remote_ip;
 
 
        sizeof_remote_ip = sizeof(remote_ip);
        sizeof_remote_ip = sizeof(remote_ip);
        fd = accept(channel->socket_fd, (struct sockaddr*)&remote_ip, &sizeof_remote_ip);
        fd = accept(channel->socket_fd, (struct sockaddr*)&remote_ip, &sizeof_remote_ip);
        if (fd < 0) {
        if (fd < 0) {
                if (channel->nonblocking) {
                if (channel->nonblocking) {
                        /* Not an error if there is not yet a remote connection - try again later */
                        /* Not an error if there is not yet a remote connection - try again later */
                        if (errno == EAGAIN)
                        if (errno == EAGAIN)
                                return 0;
                                return 0;
                }
                }
                perror("Couldn't accept connection");
                perror("Couldn't accept connection");
                return -1;
                return -1;
        }
        }
 
 
        channel->fds.fdin = channel->fds.fdout = fd;
        channel->fds.fdin = channel->fds.fdout = fd;
        close(channel->socket_fd);
        close(channel->socket_fd);
        channel->socket_fd = -1;
        channel->socket_fd = -1;
    channel->connected = 1;
    channel->connected = 1;
        return 1;
        return 1;
}
}
 
 
static int tcp_read(void * data, char * buffer, int size)
static int tcp_read(void * data, char * buffer, int size)
{
{
        struct tcp_channel* channel = data;
        struct tcp_channel* channel = data;
 
 
        /* Lazily connect to tcp partner on read/write */
        /* Lazily connect to tcp partner on read/write */
        if (!channel->connected) {
        if (!channel->connected) {
                int retval = wait_for_tcp_connect(data);
                int retval = wait_for_tcp_connect(data);
                if (retval <= 0)
                if (retval <= 0)
                        return retval;
                        return retval;
        }
        }
        return fd_read(data, buffer, size);
        return fd_read(data, buffer, size);
}
}
 
 
static int tcp_write(void * data, const char * buffer, int size)
static int tcp_write(void * data, const char * buffer, int size)
{
{
        struct tcp_channel* channel = data;
        struct tcp_channel* channel = data;
 
 
        /* Lazily connect to tcp partner on read/write */
        /* Lazily connect to tcp partner on read/write */
        if (!channel->connected) {
        if (!channel->connected) {
                int retval = wait_for_tcp_connect(data);
                int retval = wait_for_tcp_connect(data);
                if (retval < 0)
                if (retval < 0)
                        return retval;
                        return retval;
        }
        }
        return fd_write(data, buffer, size);
        return fd_write(data, buffer, size);
}
}
 
 
struct channel_ops tcp_channel_ops =
struct channel_ops tcp_channel_ops =
{
{
        init:   tcp_init,
        init:   tcp_init,
        open:   tcp_open,
        open:   tcp_open,
        close:  generic_close,
        close:  generic_close,
        read:   tcp_read,
        read:   tcp_read,
        write:  tcp_write,
        write:  tcp_write,
        free:   generic_free,
        free:   generic_free,
};
};
 
 
/*
/*
 * Local variables:
 * Local variables:
 * c-file-style: "linux"
 * c-file-style: "linux"
 * End:
 * End:
 */
 */
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.