sbuf.c revision 8b23a6c7e1aee255004dd19098d4c2462b61b849
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski. 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright. 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_free(SBuf sb) 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(sb->sb_data); 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_drop(SBuf sb, int num) 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We can only drop how much we have 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This should never succeed 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(num > sb->sb_cc) 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project num = sb->sb_cc; 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc -= num; 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr += num; 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen) 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr -= sb->sb_datalen; 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_reserve(SBuf sb, int size) 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_datalen == size) 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size); 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc = 0; 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_wptr) 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_datalen = size; 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_datalen = 0; 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Try and write() to the socket, whatever doesn't get written 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * append to the buffer... for a host with a fast net connection, 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * this prevents an unnecessary copy of the data 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (the socket is non-blocking, so we won't hang) 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_append(struct socket *so, MBuf m) 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret = 0; 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sbuf_append"); 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m = %lx", (long)m); 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m->m_len = %d", m->m_len); 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shouldn't happen, but... e.g. foreign host closes connection */ 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_len <= 0) { 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mbuf_free(m); 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there is urgent data, call sosendoob 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if not all was sent, sowrite will take care of the rest 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (The rest of this function is just an optimisation) 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_urgc) { 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sbuf_appendsb(&so->so_rcv, m); 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mbuf_free(m); 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sosendoob(so); 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We only write if there's nothing in the buffer, 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ottherwise it'll arrive out of order, and hence corrupt 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!so->so_rcv.sb_cc) { 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = socket_send(so->s, m->m_data, m->m_len); 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret <= 0) { 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Nothing was written 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * It's possible that the socket has closed, but 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we don't need to check because if it has closed, 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * it will be detected in the normal way by soread() 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sbuf_appendsb(&so->so_rcv, m); 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (ret != m->m_len) { 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Something was written, but not everything.. 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sbuf_appendsb the rest 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len -= ret; 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data += ret; 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sbuf_appendsb(&so->so_rcv, m); 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* else */ 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Whatever happened, we free the mbuf */ 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mbuf_free(m); 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copy the data from m into sb 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The caller is responsible to make sure there's enough room 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_appendsb(SBuf sb, MBuf m) 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int len, n, nn; 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = m->m_len; 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_wptr < sb->sb_rptr) { 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = sb->sb_rptr - sb->sb_wptr; 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n > len) n = len; 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(sb->sb_wptr, m->m_data, n); 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Do the right edge first */ 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = sb->sb_data + sb->sb_datalen - sb->sb_wptr; 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n > len) n = len; 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(sb->sb_wptr, m->m_data, n); 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= n; 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Now the left edge */ 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn = sb->sb_rptr - sb->sb_data; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn > len) nn = len; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(sb->sb_data,m->m_data+n,nn); 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n += nn; 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc += n; 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_wptr += n; 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen) 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_wptr -= sb->sb_datalen; 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copy data from sbuf to a normal, straight buffer 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Don't update the sbuf rptr, this will be 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * done in sbdrop when the data is acked 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_copy(SBuf sb, int off, int len, char* to) 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *from; 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project from = sb->sb_rptr + off; 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (from >= sb->sb_data + sb->sb_datalen) 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project from -= sb->sb_datalen; 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (from < sb->sb_wptr) { 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len > sb->sb_cc) len = sb->sb_cc; 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(to,from,len); 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* re-use off */ 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project off = (sb->sb_data + sb->sb_datalen) - from; 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (off > len) off = len; 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(to,from,off); 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= off; 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(to+off,sb->sb_data,len); 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 173