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

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_1_x/] [or1ksim/] [peripheral/] [channels/] [tcp.c] - Blame information for rev 1771

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 1308 phoenix
#include <stdlib.h>
30
#include <string.h>
31
#include <unistd.h>
32 1118 sfurman
 
33
#include "channel.h"
34
#include "generic.h"
35
#include "fd.h"
36
 
37
struct tcp_channel
38
{
39
        struct fd_channel fds;
40
        int socket_fd;                          /* Socket to listen to */
41
        int port_number;                        /* TCP port number */
42
        int connected;                          /* If 0, no remote endpoint yet */
43
        int nonblocking;                        /* If 0, read/write will block until
44
                                                                   remote client connects */
45
};
46
 
47
static void * tcp_init(const char * input)
48
{
49
        int port_number, fd, flags;
50
        struct sockaddr_in local_ip;
51
        struct tcp_channel* channel = (struct tcp_channel*)malloc(sizeof(struct tcp_channel));
52
        if (!channel)
53
                return NULL;
54
 
55
        fd = 0;
56
        channel->nonblocking = 1;
57
        channel->fds.fdin = -1;
58
        channel->fds.fdout = -1;
59
        channel->socket_fd = -1;
60
        channel->port_number = -1;
61
 
62
        port_number = atoi(input);
63
        if (port_number == 0)
64
                goto error;
65
 
66
        fd = socket(AF_INET, SOCK_STREAM, 0);
67
        if (fd < 0)
68
                goto error;
69
 
70
        flags = 1;
71
        if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0)
72
    {
73
                perror("Can not set SO_REUSEADDR option on channel socket");
74
                goto error;
75
        }
76
 
77
        memset(&local_ip, 0, sizeof(local_ip));
78
        local_ip.sin_family = AF_INET;
79
        local_ip.sin_addr.s_addr = htonl(INADDR_ANY);
80
        local_ip.sin_port = htons(port_number);
81
        if (bind(fd, (struct sockaddr*)&local_ip, sizeof(local_ip)) < 0) {
82
                perror("Can't bind local address");
83
                goto error;
84
        }
85
 
86
        if (channel->nonblocking) {
87
                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
88
                {
89
                        perror("Can not make channel socket non-blocking");
90
                        goto error;
91
                }
92
        }
93
 
94
        if (listen(fd, 1) < 0)
95
                goto error;
96
 
97
        channel->socket_fd = fd;
98
        channel->port_number = port_number;
99
        channel->connected = 0;
100
        return (void*)channel;
101
 
102
error:
103
        if (fd)
104
                close(fd);
105
        free(channel);
106
        return NULL;
107
}
108
 
109
static int tcp_open(void * data)
110
{
111
        /* Socket is opened lazily, upon first read or write, so do nothing here */
112
        return 0;
113
}
114
 
115
 
116
static int wait_for_tcp_connect(struct tcp_channel* channel)
117
{
118
        int fd, sizeof_remote_ip;
119
        struct sockaddr_in remote_ip;
120
 
121
        sizeof_remote_ip = sizeof(remote_ip);
122
        fd = accept(channel->socket_fd, (struct sockaddr*)&remote_ip, &sizeof_remote_ip);
123
        if (fd < 0) {
124
                if (channel->nonblocking) {
125
                        /* Not an error if there is not yet a remote connection - try again later */
126
                        if (errno == EAGAIN)
127
                                return 0;
128
                }
129
                perror("Couldn't accept connection");
130
                return -1;
131
        }
132
 
133
        channel->fds.fdin = channel->fds.fdout = fd;
134
        close(channel->socket_fd);
135
        channel->socket_fd = -1;
136
    channel->connected = 1;
137
        return 1;
138
}
139
 
140
static int tcp_read(void * data, char * buffer, int size)
141
{
142
        struct tcp_channel* channel = data;
143
 
144
        /* Lazily connect to tcp partner on read/write */
145
        if (!channel->connected) {
146
                int retval = wait_for_tcp_connect(data);
147
                if (retval <= 0)
148
                        return retval;
149
        }
150
        return fd_read(data, buffer, size);
151
}
152
 
153
static int tcp_write(void * data, const char * buffer, int size)
154
{
155
        struct tcp_channel* channel = data;
156
 
157
        /* Lazily connect to tcp partner on read/write */
158
        if (!channel->connected) {
159
                int retval = wait_for_tcp_connect(data);
160
                if (retval < 0)
161
                        return retval;
162
        }
163
        return fd_write(data, buffer, size);
164
}
165
 
166
struct channel_ops tcp_channel_ops =
167
{
168
        init:   tcp_init,
169
        open:   tcp_open,
170
        close:  generic_close,
171
        read:   tcp_read,
172
        write:  tcp_write,
173
        free:   generic_free,
174
};
175
 
176
/*
177
 * Local variables:
178
 * c-file-style: "linux"
179
 * End:
180
 */
181
 

powered by: WebSVN 2.1.0

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