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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [peripheral/] [channels/] [tcp.c] - Blame information for rev 1118

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1118 sfurman
/* tcp.c -- Definition of functions for peripheral to
2
 * communicate with host via a tcp socket.
3
 
4
   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
5
 
6
This file is part of OpenRISC 1000 Architectural Simulator.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
 
22
 
23
#include <stdio.h>
24
#include <sys/types.h>
25
#include <sys/socket.h>
26
#include <netinet/in.h>
27
#include <fcntl.h>
28
#include <errno.h>
29
 
30
#include "channel.h"
31
#include "generic.h"
32
#include "fd.h"
33
 
34
struct tcp_channel
35
{
36
        struct fd_channel fds;
37
        int socket_fd;                          /* Socket to listen to */
38
        int port_number;                        /* TCP port number */
39
        int connected;                          /* If 0, no remote endpoint yet */
40
        int nonblocking;                        /* If 0, read/write will block until
41
                                                                   remote client connects */
42
};
43
 
44
static void * tcp_init(const char * input)
45
{
46
        int port_number, fd, flags;
47
        struct sockaddr_in local_ip;
48
        struct tcp_channel* channel = (struct tcp_channel*)malloc(sizeof(struct tcp_channel));
49
        if (!channel)
50
                return NULL;
51
 
52
        fd = 0;
53
        channel->nonblocking = 1;
54
        channel->fds.fdin = -1;
55
        channel->fds.fdout = -1;
56
        channel->socket_fd = -1;
57
        channel->port_number = -1;
58
 
59
        port_number = atoi(input);
60
        if (port_number == 0)
61
                goto error;
62
 
63
        fd = socket(AF_INET, SOCK_STREAM, 0);
64
        if (fd < 0)
65
                goto error;
66
 
67
        flags = 1;
68
        if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0)
69
    {
70
                perror("Can not set SO_REUSEADDR option on channel socket");
71
                goto error;
72
        }
73
 
74
        memset(&local_ip, 0, sizeof(local_ip));
75
        local_ip.sin_family = AF_INET;
76
        local_ip.sin_addr.s_addr = htonl(INADDR_ANY);
77
        local_ip.sin_port = htons(port_number);
78
        if (bind(fd, (struct sockaddr*)&local_ip, sizeof(local_ip)) < 0) {
79
                perror("Can't bind local address");
80
                goto error;
81
        }
82
 
83
        if (channel->nonblocking) {
84
                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
85
                {
86
                        perror("Can not make channel socket non-blocking");
87
                        goto error;
88
                }
89
        }
90
 
91
        if (listen(fd, 1) < 0)
92
                goto error;
93
 
94
        channel->socket_fd = fd;
95
        channel->port_number = port_number;
96
        channel->connected = 0;
97
        return (void*)channel;
98
 
99
error:
100
        if (fd)
101
                close(fd);
102
        free(channel);
103
        return NULL;
104
}
105
 
106
static int tcp_open(void * data)
107
{
108
        /* Socket is opened lazily, upon first read or write, so do nothing here */
109
        return 0;
110
}
111
 
112
 
113
static int wait_for_tcp_connect(struct tcp_channel* channel)
114
{
115
        int fd, sizeof_remote_ip;
116
        struct sockaddr_in remote_ip;
117
 
118
        sizeof_remote_ip = sizeof(remote_ip);
119
        fd = accept(channel->socket_fd, (struct sockaddr*)&remote_ip, &sizeof_remote_ip);
120
        if (fd < 0) {
121
                if (channel->nonblocking) {
122
                        /* Not an error if there is not yet a remote connection - try again later */
123
                        if (errno == EAGAIN)
124
                                return 0;
125
                }
126
                perror("Couldn't accept connection");
127
                return -1;
128
        }
129
 
130
        channel->fds.fdin = channel->fds.fdout = fd;
131
        close(channel->socket_fd);
132
        channel->socket_fd = -1;
133
    channel->connected = 1;
134
        return 1;
135
}
136
 
137
static int tcp_read(void * data, char * buffer, int size)
138
{
139
        struct tcp_channel* channel = data;
140
 
141
        /* Lazily connect to tcp partner on read/write */
142
        if (!channel->connected) {
143
                int retval = wait_for_tcp_connect(data);
144
                if (retval <= 0)
145
                        return retval;
146
        }
147
        return fd_read(data, buffer, size);
148
}
149
 
150
static int tcp_write(void * data, const char * buffer, int size)
151
{
152
        struct tcp_channel* channel = data;
153
 
154
        /* Lazily connect to tcp partner on read/write */
155
        if (!channel->connected) {
156
                int retval = wait_for_tcp_connect(data);
157
                if (retval < 0)
158
                        return retval;
159
        }
160
        return fd_write(data, buffer, size);
161
}
162
 
163
struct channel_ops tcp_channel_ops =
164
{
165
        init:   tcp_init,
166
        open:   tcp_open,
167
        close:  generic_close,
168
        read:   tcp_read,
169
        write:  tcp_write,
170
        free:   generic_free,
171
};
172
 
173
/*
174
 * Local variables:
175
 * c-file-style: "linux"
176
 * End:
177
 */
178
 

powered by: WebSVN 2.1.0

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