socket.cc revision 10412
17019SBrad.Beckmann@amd.com/* 27019SBrad.Beckmann@amd.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 37019SBrad.Beckmann@amd.com * All rights reserved. 47019SBrad.Beckmann@amd.com * 57019SBrad.Beckmann@amd.com * Redistribution and use in source and binary forms, with or without 67019SBrad.Beckmann@amd.com * modification, are permitted provided that the following conditions are 77019SBrad.Beckmann@amd.com * met: redistributions of source code must retain the above copyright 87019SBrad.Beckmann@amd.com * notice, this list of conditions and the following disclaimer; 97019SBrad.Beckmann@amd.com * redistributions in binary form must reproduce the above copyright 107019SBrad.Beckmann@amd.com * notice, this list of conditions and the following disclaimer in the 117019SBrad.Beckmann@amd.com * documentation and/or other materials provided with the distribution; 127019SBrad.Beckmann@amd.com * neither the name of the copyright holders nor the names of its 137019SBrad.Beckmann@amd.com * contributors may be used to endorse or promote products derived from 147019SBrad.Beckmann@amd.com * this software without specific prior written permission. 157019SBrad.Beckmann@amd.com * 167019SBrad.Beckmann@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177019SBrad.Beckmann@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187019SBrad.Beckmann@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197019SBrad.Beckmann@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207019SBrad.Beckmann@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217019SBrad.Beckmann@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227019SBrad.Beckmann@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237019SBrad.Beckmann@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247019SBrad.Beckmann@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257019SBrad.Beckmann@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267019SBrad.Beckmann@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277019SBrad.Beckmann@amd.com * 287019SBrad.Beckmann@amd.com * Authors: Nathan Binkert 297019SBrad.Beckmann@amd.com */ 306876Ssteve.reinhardt@amd.com 316882SBrad.Beckmann@amd.com#include <netinet/in.h> 3213892Sgabeblack@google.com#include <netinet/tcp.h> 336876Ssteve.reinhardt@amd.com#include <sys/socket.h> 3413892Sgabeblack@google.com#include <sys/types.h> 3511308Santhony.gutierrez@amd.com#include <unistd.h> 3611308Santhony.gutierrez@amd.com 3711308Santhony.gutierrez@amd.com#include <cerrno> 3811308Santhony.gutierrez@amd.com 3910090Snilay@cs.wisc.edu#include "base/misc.hh" 4011308Santhony.gutierrez@amd.com#include "base/socket.hh" 4111308Santhony.gutierrez@amd.com#include "base/types.hh" 4211308Santhony.gutierrez@amd.com 4311308Santhony.gutierrez@amd.comusing namespace std; 4411308Santhony.gutierrez@amd.com 4511308Santhony.gutierrez@amd.combool ListenSocket::listeningDisabled = false; 4610090Snilay@cs.wisc.edubool ListenSocket::anyListening = false; 4711308Santhony.gutierrez@amd.com 4811308Santhony.gutierrez@amd.comvoid 4911308Santhony.gutierrez@amd.comListenSocket::disableAll() 5011308Santhony.gutierrez@amd.com{ 5111308Santhony.gutierrez@amd.com if (anyListening) 5211308Santhony.gutierrez@amd.com panic("Too late to disable all listeners, already have a listener"); 5311308Santhony.gutierrez@amd.com listeningDisabled = true; 548932SBrad.Beckmann@amd.com} 558706Sandreas.hansson@arm.com 5611308Santhony.gutierrez@amd.combool 5711308Santhony.gutierrez@amd.comListenSocket::allDisabled() 5810919Sbrandon.potter@amd.com{ 596876Ssteve.reinhardt@amd.com return listeningDisabled; 6011308Santhony.gutierrez@amd.com} 6111308Santhony.gutierrez@amd.com 6211308Santhony.gutierrez@amd.com//////////////////////////////////////////////////////////////////////// 6310090Snilay@cs.wisc.edu// 6411308Santhony.gutierrez@amd.com// 6511308Santhony.gutierrez@amd.com 6611308Santhony.gutierrez@amd.comListenSocket::ListenSocket() 6711308Santhony.gutierrez@amd.com : listening(false), fd(-1) 6811308Santhony.gutierrez@amd.com{} 6911308Santhony.gutierrez@amd.com 7011308Santhony.gutierrez@amd.comListenSocket::~ListenSocket() 7111308Santhony.gutierrez@amd.com{ 7211308Santhony.gutierrez@amd.com if (fd != -1) 7311308Santhony.gutierrez@amd.com close(fd); 7411308Santhony.gutierrez@amd.com} 7511308Santhony.gutierrez@amd.com 7611660Stushar@ece.gatech.edu// Create a socket and configure it for listening 7711308Santhony.gutierrez@amd.combool 7811308Santhony.gutierrez@amd.comListenSocket::listen(int port, bool reuse) 7911308Santhony.gutierrez@amd.com{ 806876Ssteve.reinhardt@amd.com if (listening) 8111339SMichael.Lebeane@amd.com panic("Socket already listening!"); 8211308Santhony.gutierrez@amd.com 8311308Santhony.gutierrez@amd.com fd = ::socket(PF_INET, SOCK_STREAM, 0); 8411702Smichael.lebeane@amd.com if (fd < 0) 85 panic("Can't create socket:%s !", strerror(errno)); 86 87 if (reuse) { 88 int i = 1; 89 if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i, 90 sizeof(i)) < 0) 91 panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!"); 92 } 93 94 struct sockaddr_in sockaddr; 95 sockaddr.sin_family = PF_INET; 96 sockaddr.sin_addr.s_addr = INADDR_ANY; 97 sockaddr.sin_port = htons(port); 98 // finally clear sin_zero 99 memset(&sockaddr.sin_zero, 0, sizeof(sockaddr.sin_zero)); 100 int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr)); 101 if (ret != 0) { 102 if (ret == -1 && errno != EADDRINUSE) 103 panic("ListenSocket(listen): bind() failed!"); 104 return false; 105 } 106 107 if (::listen(fd, 1) == -1) { 108 if (errno != EADDRINUSE) 109 panic("ListenSocket(listen): listen() failed!"); 110 111 return false; 112 } 113 114 listening = true; 115 anyListening = true; 116 return true; 117} 118 119 120// Open a connection. Accept will block, so if you don't want it to, 121// make sure a connection is ready before you call accept. 122int 123ListenSocket::accept(bool nodelay) 124{ 125 struct sockaddr_in sockaddr; 126 socklen_t slen = sizeof (sockaddr); 127 int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen); 128 if (sfd != -1 && nodelay) { 129 int i = 1; 130 if (::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, 131 sizeof(i)) < 0) 132 warn("ListenSocket(accept): setsockopt() TCP_NODELAY failed!"); 133 } 134 135 return sfd; 136} 137