socket.c revision e3f3f4c91f374a058586a2f5421aee22d42f9621
553N/A * Copyright (c) 1995 Danny Gasparovski. 45N/A * Please read the file COPYRIGHT for the 45N/A * terms and conditions of the copyright. 45N/A * Create a new socket, initialise the fields 45N/A * It is the responsibility of the caller to 45N/A * insque() it into the correct linked-list * remque and free a socket, clobber cache /*Take global mutexes of udb and tcb, because we dont know which is mutex */ /*XXX: don't forget to set correct so_type in corresponded attach operation */ /* socket's mutex could be released because socket none accessible via queue anymore*/ * Read from so's socket into sb_snd, updating all relevant sbuf fields * NOTE: This will only be called if it is select()ed for reading, so * a read() of 0 (or less) means it's disconnected * No need to check if there's enough room to read. * soread wouldn't have been called if there weren't /* Should never succeed, but... */ /* Should never succeed, but... */ * If there was no error, try and read the second time round * We read again if n = 2 (ie, there's another part of the buffer) * and we read as much as we could in the first read * We don't test for <= 0 this time, because there legitimately * might not be any more data (since the socket is non-blocking), * a close will be detected on next iteration. * A return of -1 wont (shouldn't) happen, since it didn't happen above * When the socket is created, we set it SO_OOBINLINE, * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data * We take a guess at how much urgent data has arrived. * In most situations, when urgent data arrives, the next * read() should get all the urgent data. This guess will * be wrong however if more data arrives just after the * urgent data, or the read() doesn't return all the * There's a lot duplicated code here, but... char buff[
2048];
/* XXX Shouldn't be sending more oob data than this */ /* We can send it directly */ * Since there's no sendv or sendtov like writev, * we must copy all data to a linear buffer then * Write data from so_rcv to so's socket, * updating all sbuf field as necessary * No need to check if there's something to write, * sowrite wouldn't have been called otherwise /* Should never succeed, but... */ /* Check if there's urgent data to send, and if so, send it */ /* This should never happen, but people tell me it does *shrug* */ DEBUG_MISC((
dfd,
" --- sowrite disconnected, so->so_state = %x, errno = %d\n",
* If in DRAIN mode, and there's no more data, set * recvfrom() a UDP socket /* XXX Check if reply is "correct"? */ so->
so_m = 0;
/* Don't m_free() it again! */ /* No need for this socket anymore, udp_detach it */ }
else {
/* A "normal" UDP packet */ * XXX Shouldn't FIONREAD packets destined for port 53, * but I don't know the max packet size for DNS lookups /* if (so->so_fport != htons(53)) { */ * Hack: domain name lookup will be used the most for UDP, * and since they'll only be used once there's no need * for the 4 minute (or whatever) timeout... So we time them * out much quicker (10 seconds for now...) /* if (m->m_len == len) { * If this packet was destined for CTL_ADDR, * make it look like that's where it came from, done by udp_output /* handle this case at 'default:' */ /* Send the packet to host to fully emulate broadcast */ /** @todo r=klaus: on Linux host this causes the host to receive * the packet twice for some reason. And I cannot find any place * in the man pages which states that sending a broadcast does not * reach the host itself. */ /* Don't care what port we get */ * Kill the socket if there's no reply in 4 minutes, * but only if it's an expirable socket * XXX This should really be tcp_listen /* free(so); Not sofree() ??? free(NULL) == NOP */ /* Don't tcp_attach... we don't need so_snd nor so_rcv */ /*after adding to global queue probably we should keep lock*/ * SS_FACCEPTONCE sockets must time out. /* Restore the real errno */ int tmperrno =
errno;
/* Don't clobber the real reason we failed */ /* Restore the real errno */ * Data is available in so_rcv * Just write() the data to the socket /* FD_CLR(so->s,&writefds); */ * Data has been freed in so_snd * We have room for a read() if we want to * For now, don't read, it'll be done in the main loop * Various session state calls * XXX Should be #define's * The socket state stuff needs work, these often get call 2 or 3 * times each when only 1 was needed /* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */ /* so->so_state = SS_ISFDISCONNECTED; */ * Set CANTSENDMORE once all data has been write()n