|
|
1.1 ! root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.