ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/sbuf.c
Revision: 1.1
Committed: 2005-05-13T09:00:59Z (19 years, 6 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: nigel-build-19, nigel-build-17
Log Message:
slirp user mode network emulation code from qemu

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * Copyright (c) 1995 Danny Gasparovski.
3     *
4     * Please read the file COPYRIGHT for the
5     * terms and conditions of the copyright.
6     */
7    
8     #include <slirp.h>
9    
10     /* Done as a macro in socket.h */
11     /* int
12     * sbspace(struct sockbuff *sb)
13     * {
14     * return SB_DATALEN - sb->sb_cc;
15     * }
16     */
17    
18     void
19     sbfree(sb)
20     struct sbuf *sb;
21     {
22     free(sb->sb_data);
23     }
24    
25     void
26     sbdrop(sb, num)
27     struct sbuf *sb;
28     int num;
29     {
30     /*
31     * We can only drop how much we have
32     * This should never succeed
33     */
34     if(num > sb->sb_cc)
35     num = sb->sb_cc;
36     sb->sb_cc -= num;
37     sb->sb_rptr += num;
38     if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
39     sb->sb_rptr -= sb->sb_datalen;
40    
41     }
42    
43     void
44     sbreserve(sb, size)
45     struct sbuf *sb;
46     int size;
47     {
48     if (sb->sb_data) {
49     /* Already alloced, realloc if necessary */
50     if (sb->sb_datalen != size) {
51     sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
52     sb->sb_cc = 0;
53     if (sb->sb_wptr)
54     sb->sb_datalen = size;
55     else
56     sb->sb_datalen = 0;
57     }
58     } else {
59     sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
60     sb->sb_cc = 0;
61     if (sb->sb_wptr)
62     sb->sb_datalen = size;
63     else
64     sb->sb_datalen = 0;
65     }
66     }
67    
68     /*
69     * Try and write() to the socket, whatever doesn't get written
70     * append to the buffer... for a host with a fast net connection,
71     * this prevents an unnecessary copy of the data
72     * (the socket is non-blocking, so we won't hang)
73     */
74     void
75     sbappend(so, m)
76     struct socket *so;
77     struct mbuf *m;
78     {
79     int ret = 0;
80    
81     DEBUG_CALL("sbappend");
82     DEBUG_ARG("so = %lx", (long)so);
83     DEBUG_ARG("m = %lx", (long)m);
84     DEBUG_ARG("m->m_len = %d", m->m_len);
85    
86     /* Shouldn't happen, but... e.g. foreign host closes connection */
87     if (m->m_len <= 0) {
88     m_free(m);
89     return;
90     }
91    
92     /*
93     * If there is urgent data, call sosendoob
94     * if not all was sent, sowrite will take care of the rest
95     * (The rest of this function is just an optimisation)
96     */
97     if (so->so_urgc) {
98     sbappendsb(&so->so_rcv, m);
99     m_free(m);
100     sosendoob(so);
101     return;
102     }
103    
104     /*
105     * We only write if there's nothing in the buffer,
106     * ottherwise it'll arrive out of order, and hence corrupt
107     */
108     if (!so->so_rcv.sb_cc)
109     ret = send(so->s, m->m_data, m->m_len, 0);
110    
111     if (ret <= 0) {
112     /*
113     * Nothing was written
114     * It's possible that the socket has closed, but
115     * we don't need to check because if it has closed,
116     * it will be detected in the normal way by soread()
117     */
118     sbappendsb(&so->so_rcv, m);
119     } else if (ret != m->m_len) {
120     /*
121     * Something was written, but not everything..
122     * sbappendsb the rest
123     */
124     m->m_len -= ret;
125     m->m_data += ret;
126     sbappendsb(&so->so_rcv, m);
127     } /* else */
128     /* Whatever happened, we free the mbuf */
129     m_free(m);
130     }
131    
132     /*
133     * Copy the data from m into sb
134     * The caller is responsible to make sure there's enough room
135     */
136     void
137     sbappendsb(sb, m)
138     struct sbuf *sb;
139     struct mbuf *m;
140     {
141     int len, n, nn;
142    
143     len = m->m_len;
144    
145     if (sb->sb_wptr < sb->sb_rptr) {
146     n = sb->sb_rptr - sb->sb_wptr;
147     if (n > len) n = len;
148     memcpy(sb->sb_wptr, m->m_data, n);
149     } else {
150     /* Do the right edge first */
151     n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
152     if (n > len) n = len;
153     memcpy(sb->sb_wptr, m->m_data, n);
154     len -= n;
155     if (len) {
156     /* Now the left edge */
157     nn = sb->sb_rptr - sb->sb_data;
158     if (nn > len) nn = len;
159     memcpy(sb->sb_data,m->m_data+n,nn);
160     n += nn;
161     }
162     }
163    
164     sb->sb_cc += n;
165     sb->sb_wptr += n;
166     if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
167     sb->sb_wptr -= sb->sb_datalen;
168     }
169    
170     /*
171     * Copy data from sbuf to a normal, straight buffer
172     * Don't update the sbuf rptr, this will be
173     * done in sbdrop when the data is acked
174     */
175     void
176     sbcopy(sb, off, len, to)
177     struct sbuf *sb;
178     int off;
179     int len;
180     char *to;
181     {
182     char *from;
183    
184     from = sb->sb_rptr + off;
185     if (from >= sb->sb_data + sb->sb_datalen)
186     from -= sb->sb_datalen;
187    
188     if (from < sb->sb_wptr) {
189     if (len > sb->sb_cc) len = sb->sb_cc;
190     memcpy(to,from,len);
191     } else {
192     /* re-use off */
193     off = (sb->sb_data + sb->sb_datalen) - from;
194     if (off > len) off = len;
195     memcpy(to,from,off);
196     len -= off;
197     if (len)
198     memcpy(to+off,sb->sb_data,len);
199     }
200     }
201