![]() ![]() | ![]() |
1.1 root 1: /*
2: * Copyright (c) 1995 Danny Gasparovski.
1.1.1.2 root 3: *
4: * Please read the file COPYRIGHT for the
1.1 root 5: * terms and conditions of the copyright.
6: */
7:
8: #include <slirp.h>
9:
1.1.1.2 root 10: static void sbappendsb(struct sbuf *sb, struct mbuf *m);
11:
1.1 root 12: /* Done as a macro in socket.h */
13: /* int
1.1.1.2 root 14: * sbspace(struct sockbuff *sb)
1.1 root 15: * {
16: * return SB_DATALEN - sb->sb_cc;
17: * }
18: */
19:
20: void
21: sbfree(sb)
22: struct sbuf *sb;
23: {
24: free(sb->sb_data);
25: }
26:
27: void
28: sbdrop(sb, num)
29: struct sbuf *sb;
1.1.1.2 root 30: int num;
1.1 root 31: {
1.1.1.2 root 32: /*
1.1 root 33: * We can only drop how much we have
1.1.1.2 root 34: * This should never succeed
1.1 root 35: */
36: if(num > sb->sb_cc)
37: num = sb->sb_cc;
38: sb->sb_cc -= num;
39: sb->sb_rptr += num;
40: if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
41: sb->sb_rptr -= sb->sb_datalen;
1.1.1.2 root 42:
1.1 root 43: }
44:
45: void
46: sbreserve(sb, size)
47: struct sbuf *sb;
48: int size;
49: {
50: if (sb->sb_data) {
51: /* Already alloced, realloc if necessary */
52: if (sb->sb_datalen != size) {
53: sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
54: sb->sb_cc = 0;
55: if (sb->sb_wptr)
56: sb->sb_datalen = size;
57: else
58: sb->sb_datalen = 0;
59: }
60: } else {
61: sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
62: sb->sb_cc = 0;
63: if (sb->sb_wptr)
64: sb->sb_datalen = size;
65: else
66: sb->sb_datalen = 0;
67: }
68: }
69:
70: /*
71: * Try and write() to the socket, whatever doesn't get written
72: * append to the buffer... for a host with a fast net connection,
73: * this prevents an unnecessary copy of the data
74: * (the socket is non-blocking, so we won't hang)
75: */
76: void
77: sbappend(so, m)
78: struct socket *so;
79: struct mbuf *m;
80: {
81: int ret = 0;
1.1.1.2 root 82:
1.1 root 83: DEBUG_CALL("sbappend");
84: DEBUG_ARG("so = %lx", (long)so);
85: DEBUG_ARG("m = %lx", (long)m);
86: DEBUG_ARG("m->m_len = %d", m->m_len);
1.1.1.2 root 87:
1.1 root 88: /* Shouldn't happen, but... e.g. foreign host closes connection */
89: if (m->m_len <= 0) {
90: m_free(m);
91: return;
92: }
1.1.1.2 root 93:
1.1 root 94: /*
95: * If there is urgent data, call sosendoob
96: * if not all was sent, sowrite will take care of the rest
97: * (The rest of this function is just an optimisation)
98: */
99: if (so->so_urgc) {
100: sbappendsb(&so->so_rcv, m);
101: m_free(m);
102: sosendoob(so);
103: return;
104: }
1.1.1.2 root 105:
1.1 root 106: /*
107: * We only write if there's nothing in the buffer,
108: * ottherwise it'll arrive out of order, and hence corrupt
109: */
110: if (!so->so_rcv.sb_cc)
1.1.1.3 ! root 111: ret = slirp_send(so, m->m_data, m->m_len, 0);
1.1.1.2 root 112:
1.1 root 113: if (ret <= 0) {
1.1.1.2 root 114: /*
1.1 root 115: * Nothing was written
116: * It's possible that the socket has closed, but
117: * we don't need to check because if it has closed,
118: * it will be detected in the normal way by soread()
119: */
120: sbappendsb(&so->so_rcv, m);
121: } else if (ret != m->m_len) {
122: /*
123: * Something was written, but not everything..
124: * sbappendsb the rest
125: */
126: m->m_len -= ret;
127: m->m_data += ret;
128: sbappendsb(&so->so_rcv, m);
129: } /* else */
130: /* Whatever happened, we free the mbuf */
131: m_free(m);
132: }
133:
134: /*
135: * Copy the data from m into sb
136: * The caller is responsible to make sure there's enough room
137: */
1.1.1.2 root 138: static void
139: sbappendsb(struct sbuf *sb, struct mbuf *m)
1.1 root 140: {
141: int len, n, nn;
1.1.1.2 root 142:
1.1 root 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;
1.1.1.2 root 183:
1.1 root 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: }